Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YAML] Fix processing timestamp strings with timezone #20550

Merged
merged 1 commit into from Nov 18, 2016

Conversation

noahheck
Copy link
Contributor

@noahheck noahheck commented Nov 17, 2016

Q A
Branch? 3.1
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #20399
License MIT
Doc PR -

Parse date strings containing timezone data correctly
Default date strings not containing timezone data to UTC

// Timestamps that have timezone data should be parsed in the specified timezone first, then
// converted to UTC; if no tz data is supplied, parse as UTC date initially
if (isset($datetimeMatches['tz'])) {
$date = new \DateTime($scalar);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing $datetimeMatches['tz'] here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timezone data is in the string ($scalar) so no need to add it to the constructor.

@stof
Copy link
Member

stof commented Nov 17, 2016

Tests are needed to cover this

@noahheck
Copy link
Contributor Author

@stof There are tests for this, but they were failing in non-UTC timezone: #20551

@xabbuh
Copy link
Member

xabbuh commented Nov 17, 2016

#20551 should make such bugs visible in the future. So yes, I agree that we don't have to update the tests.

@ro0NL
Copy link
Contributor

ro0NL commented Nov 17, 2016

@nicolas-grekas why did you removed BC break label? :)

@@ -535,7 +535,11 @@ public function testParseNestedTimestampListAsDateTimeObject($yaml, $year, $mont
$expected = new \DateTime($yaml);
$expected->setTimeZone(new \DateTimeZone('UTC'));
$expected->setDate($year, $month, $day);
@$expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was intended to cover HHVM. Not sure we should remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch is just adding consistency with another test in the same file. Looks like we missed it, maybe during a merge.

Copy link
Contributor

@ro0NL ro0NL Nov 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found it :) #20291 (comment)

Ah.. i see the inconsistency now 👍

@nicolas-grekas
Copy link
Member

@ro0NL why should we keep it in the first place?

@ro0NL
Copy link
Contributor

ro0NL commented Nov 17, 2016

Keep what? The spec is correct now, but the BC break is real right? Before system timezone was the default, now UTC 😕

@noahheck
Copy link
Contributor Author

@ro0NL All parsed DateTimes were converted to UTC. Before, the system timezone was used only used if there wasn't timezone information in the timestamp string. The DateTime was then converted to UTC time, but converting had the possibility of changing the representation. The returned DateTime will still be in UTC, just without the value being changed.

I don't know if that constitutes a BC break (?)

@ro0NL
Copy link
Contributor

ro0NL commented Nov 18, 2016

Before datetimes without a timezone assumed the system timezone, before UTC conversion. Now UTC is assumed.. (ie. no conversion happens).

What about this approach?

// in 4.0
// return new \DateTime($scalar, new \DateTimeZone('UTC'));

if ('UTC' !== date_default_timezone_get()) {
   // trigger deprecation: datetimes without a timezone are assumed UTC in 4.0 instead of the system timezone
}

// current code, ie.
$date = new \DateTime($scalar);
$date->setTimeZone(new \DateTimeZone('UTC'));

return $date;

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Nov 18, 2016

@ro0NL a deprecation is something that a user must be able to resolve by changing its code. Not the case here. This is clearly a bug to me. Every bug fix is a behavior change by definition.

@ro0NL
Copy link
Contributor

ro0NL commented Nov 18, 2016

You can change the datetime value, so it includes the timezone explicitly. Which is only needed, if the system timezone is not UTC already. This gives correct YAML, as well as the expected value.

Just saying this can lead to tricky side effects, as we get a total different time value.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Nov 18, 2016

Changing a date definition in yaml to workaround a parser implementation bug is definitely not a "code fix"...

if (Yaml::PARSE_DATETIME & $flags) {
$date = new \DateTime($scalar);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given @nicolas-grekas comment, it could simply be

$date = new \DateTime($scalar, new \DateTimeZone('UTC'));
$date->setTimeZone(new \DateTimeZone('UTC'));

return $date;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

@stof
Copy link
Member

stof commented Nov 18, 2016

If the Yaml timestamp does not include the timezone info, parsing it as a UTC timestamp is the right thing to do according the behavior of the official PyYaml parser.
So 👍 for this

@ro0NL
Copy link
Contributor

ro0NL commented Nov 18, 2016

Would a changelog help? To clarify, i know configs defining a datetime value (some specific 'since' date that is updated once in a while) which will now silently fetch data from one hour earlier than expected (system tz = +01:00).

People should be aware of this change, to update accordingly.

@nicolas-grekas
Copy link
Member

👍

nicolas-grekas added a commit that referenced this pull request Nov 18, 2016
This PR was merged into the 2.7 branch.

Discussion
----------

[ci] Testing with UTC hides bugs

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

As shown by #20550, we're having bugs because we don't in proper TZ conditions.
Let's do Europe on Travis, and America on Windows.

Commits
-------

e0f9bda [ci] Testing with UTC hides bugs
@nicolas-grekas
Copy link
Member

@ro0NL this will be in the usual changelog and github history.

@ro0NL
Copy link
Contributor

ro0NL commented Nov 18, 2016

Correct.. i meant a upgrade note actually. But i guess this is fine then, lets see what happens :)

👍

Parse date strings containing timezone data correctly
Default date strings not containing timezone data to UTC
@nicolas-grekas
Copy link
Member

In fact, this bug comes from #20291 which is quite recent.
I reverted the UTC normalization behavior that I wrongly introduced then, and added test cases for the correct behavior (preserving TZ info).

@nicolas-grekas
Copy link
Member

Thank you @noahheck.

@nicolas-grekas nicolas-grekas merged commit cdb11a7 into symfony:3.1 Nov 18, 2016
nicolas-grekas added a commit that referenced this pull request Nov 18, 2016
…sain)

This PR was merged into the 3.1 branch.

Discussion
----------

[YAML] Fix processing timestamp strings with timezone

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #20399
| License       | MIT
| Doc PR        | -

Parse date strings containing timezone data correctly
Default date strings not containing timezone data to UTC

Commits
-------

cdb11a7 [YAML] Fix processing timestamp with timezone
@fabpot fabpot mentioned this pull request Nov 21, 2016
@NicoHaase
Copy link
Contributor

NicoHaase commented Nov 21, 2016

In Travis, you can run test builds using a configuration matrix. I think, such a feature could help to run these tests more thoroughly. Running with configuration A on one test server and B on another introduces new ways of bugs. Running with configuration A AND B on one server and the same configurations on another server sounds much better

//edit: sorry, this should go to e968d0f

@nicolas-grekas
Copy link
Member

We care a lot about the total time it takes for our CI to complete. Doing this wouldn't provide any more safety to me, but make tests run slower.

@NicoHaase
Copy link
Contributor

Travis builds should run parallel, so you start one run using one timezone setting and another run using the different setting at the same time. It should not take noticable more time to run tests with multiple settings.

In my opinion: if there is the possibility that Symfony behaves differently for different settings, all such combinations should be tested to ensure that Symfony behaves correctly in all these settings. Skipping combinations to fasten up the test suite sounds like the wrong way

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Nov 21, 2016

We're not skipping combinations, we're just splitting them to several ci providers.
And even if tests run in // (which is already the case right now of course), since the number of jobs is limited, adding more jobs would still slow down the ci experience when people submit several PRs concurrently, which happens a lot on an active project like Sf.

@fabpot fabpot mentioned this pull request Nov 27, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants