8000 properly parse dates before the Gregorian calendar · symfony/symfony@92b56a7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 92b56a7

Browse files
xabbuhconnorhu
authored andcommitted
properly parse dates before the Gregorian calendar
1 parent e49f84b commit 92b56a7

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ public function transform(mixed $dateTime): string
8282
throw new TransformationFailedException('Expected a \DateTimeInterface.');
8383
}
8484

85-
$value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp());
85+
$timestamp = $this->getCalendarConvertingFormatter()->parse($dateTime->format('Y-m-d H:i:s'));
86+
$value = $this->getIntlDateFormatter()->format($timestamp);
8687

8788
if (0 != intl_get_error_code()) {
8889
throw new TransformationFailedException(intl_get_error_message());
@@ -134,7 +135,7 @@ public function reverseTransform(mixed $value): ?\DateTime
134135
try {
135136
if ($dateOnly) {
136137
// we only care about year-month-date, which has been delivered as a timestamp pointing to UTC midnight
137-
$dateTime = new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->outputTimezone));
138+
$dateTime = new \DateTime($this->getCalendarConvertingFormatter()->format($timestamp), new \DateTimeZone($this->outputTimezone));
138139
} else {
139140
// read timestamp into DateTime object - the formatter delivers a timestamp
140141
$dateTime = new \DateTime(sprintf('@%s', $timestamp));
@@ -196,4 +197,11 @@ protected function isPatternDateOnly(): bool
196197
// check for the absence of time-related placeholders
197198
return 0 === preg_match('#[ahHkKmsSAzZOvVxX]#', $pattern);
198199
}
200+
201+
private function getCalendarConvertingFormatter(): \IntlDateFormatter
202+
{
203+
$timezone = $this->isPatternDateOnly() ? 'UTC' : $this->inputTimezone;
204+
205+
return new \IntlDateFormatter(\Locale::getDefault(), \IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, new \DateTimeZone($timezone), \IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd HH:mm:ss');
C87B
206+
}
199207
}

src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,4 +1160,19 @@ protected function getTestOptions(): array
11601160
{
11611161
return ['widget' => 'choice'];
11621162
}
1163+
1164+
public function testSubmitDateBeforeBeginningOfGregorianCalendar()
1165+
{
1166+
if (\PHP_INT_SIZE < 8) {
1167+
$this->markTestSkipped('Parsing three digits years requires a 64bit PHP.');
1168+
}
1169+
1170+
$form = $this->factory->create(static::TESTED_TYPE, null, [
1171+
'widget' => 'single_text',
1172+
]);
1173+
$form->submit('950-12-19');
1174+
1175+
$this->assertSame('0950-12-19', $form->getData()->format('Y-m-d'));
1176+
$this->assertSame('0950-12-19', $form->getViewData());
1177+
}
11631178
}

0 commit comments

Comments
 (0)
0