Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e043316

Browse filesBrowse 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
Copy full SHA for e043316

File tree

2 files changed

+15
-11
lines changed
Filter options

2 files changed

+15
-11
lines changed

‎src/Symfony/Component/Validator/ConstraintValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/ConstraintValidator.php
+5-9Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php
+10-2Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.