8000 bug #34904 [Validator][ConstraintValidator] Safe fail on invalid time… · symfony/symfony@e043316 · GitHub
[go: up one dir, main page]

Skip to content

Commit e043316

Browse files
bug #34904 [Validator][ConstraintValidator] Safe fail on invalid timezones (fancyweb)
This PR was merged into the 3.4 branch. Discussion ---------- [Validator][ConstraintValidator] Safe fail on invalid timezones Co-authored-by: Scott Dawson <scott@loyaltycorp.com.au> | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #33901 | License | MIT | Doc PR | Alternative to #33902. I will explain why I think it is better this way: 1. We set the timezone with the setter because it's 100% safe, it never fails. It fall backs to the default timezone if the provided timezone is not supported (as if we passed null, so the same behavior that always existed). We are therefore compatible with all edge cases. 2. We don't validate the timezone with `\DateTimeZone::listIdentifiers()`. It only returns full identifiers like "Europe/Paris" but it doesn't take into account "numeric" identifiers such as "+08:00" which are perfectly valid. I added a test case to ensure we stay valid with this case. + some invalid identifiers for the native `\IntlDateFormatter` are valid with the polyfill that uses `\DateTimeZone` (eg : `X`). I don't think we can validate anything safely that will work reliably on both implementations. Commits ------- 3b1b994 [Validator][ConstraintValidator] Safe fail on invalid timezones
2 parents 4ec093a + 3b1b994 commit e043316

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

src/Symfony/Component/Validator/ConstraintValidator.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,12 @@ protected function formatValue($value, $format = 0)
8787
{
8888
if (($format & self::PRETTY_DATE) && $value instanceof \DateTimeInterface) {
8989
if (class_exists('IntlDateFormatter')) {
90-
$locale = \Locale::getDefault();
91-
$formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, $value->getTimezone());
90+
$formatter = new \IntlDateFormatter(\Locale::getDefault(), \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, 'UTC');
9291

93-
// neither the native nor the stub IntlDateFormatter support
94-
// DateTimeImmutable as of yet
95-
if (!$value instanceof \DateTime) {
96-
$value = new \DateTime($value->format('Y-m-d H:i:s.u e'));
97-
}
98-
99-
return $formatter->format($value);
92+
return $formatter->format(new \DateTime(
93+
$value->format('Y-m-d H:i:s.u'),
94+
new \DateTimeZone('UTC')
95+
));
10096
}
10197

10298
return $value->format('Y-m-d H:i:s');

src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public function testFormatValue($expected, $value, $format = 0)
2727

2828
public function formatValueProvider()
2929
{
30+
$defaultTimezone = date_default_timezone_get();
31+
date_default_timezone_set('Europe/Moscow'); // GMT+3
32+
3033
$data = [
3134
['true', true],
3235
['false', false],
@@ -36,10 +39,15 @@ public function formatValueProvider()
3639
['array', []],
3740
['object', $toString = new TestToStringObject()],
3841
['ccc', $toString, ConstraintValidator::OBJECT_TO_STRING],
39-
['object', $dateTime = (new \DateTimeImmutable('@0'))->setTimezone(new \DateTimeZone('UTC'))],
40-
[class_exists(\IntlDateFormatter::class) ? 'Jan 1, 1970, 12:00 AM' : '1970-01-01 00:00:00', $dateTime, ConstraintValidator::PRETTY_DATE],
42+
['object', $dateTime = new \DateTimeImmutable('1971-02-02T08:00:00UTC')],
43+
[class_exists(\IntlDateFormatter::class) ? 'Oct 4, 2019, 11:02 AM' : '2019-10-04 11:02:03', new \DateTimeImmutable('2019-10-04T11:02:03+09:00'), ConstraintValidator::PRETTY_DATE],
44+
[class_exists(\IntlDateFormatter::class) ? 'Feb 2, 1971, 8:00 AM' : '1971-02-02 08:00:00', $dateTime, ConstraintValidator::PRETTY_DATE],
45+
[class_exists(\IntlDateFormatter::class) ? 'Jan 1, 1970, 6:00 AM' : '1970-01-01 06:00:00', new \DateTimeImmutable('1970-01-01T06:00:00Z'), ConstraintValidator::PRETTY_DATE],
46+
[class_exists(\IntlDateFormatter::class) ? 'Jan 1, 1970, 3:00 PM' : '1970-01-01 15:00:00', (new \DateTimeImmutable('1970-01-01T23:00:00'))->setTimezone(new \DateTimeZone('America/New_York')), ConstraintValidator::PRETTY_DATE],
4147
];
4248

49+
date_default_timezone_set($defaultTimezone);
50+
4351
return $data;
4452
}
4553
}

0 commit comments

Comments
 (0)
0