Skip to content

Commit

Permalink
[Yaml] Feature #48920 Allow milliseconds and microseconds in dates
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinwilson authored and fabpot committed Feb 4, 2023
1 parent a08a41c commit 8afb4c7
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 9 deletions.
28 changes: 21 additions & 7 deletions src/Symfony/Component/Yaml/Inline.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,16 @@ public static function dump(mixed $value, int $flags = 0): string

return self::dumpNull($flags);
case $value instanceof \DateTimeInterface:
return $value->format('c');
$length = \strlen(rtrim($value->format('u'), '0'));
if (0 === $length) {
$format = 'c';
} elseif ($length < 4) {
$format = 'Y-m-d\TH:i:s.vP';
} else {
$format = 'Y-m-d\TH:i:s.uP';
}

return $value->format($format);
case $value instanceof \UnitEnum:
return sprintf('!php/const %s::%s', $value::class, $value->name);
case \is_object($value):
Expand Down Expand Up @@ -712,15 +721,20 @@ private static function evaluateScalar(string $scalar, int $flags, array &$refer
return $time;
}

try {
if (false !== $scalar = $time->getTimestamp()) {
return $scalar;
$length = \strlen(rtrim($time->format('u'), '0'));
if (0 === $length) {
try {
if (false !== $scalar = $time->getTimestamp()) {
return $scalar;
}
} catch (\ValueError) {
// no-op
}
} catch (\ValueError) {
// no-op

return (int) $time->format('U');
}

return $time->format('U');
return (float) $time->format('U.u');
}
}

Expand Down
46 changes: 46 additions & 0 deletions src/Symfony/Component/Yaml/Tests/DumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,52 @@ public function testDumpIdeographicSpaces()
], 2));
}

/**
* @dataProvider getDateTimeData
*/
public function testDumpDateTime(array $input, string $expected)
{
$this->assertSame($expected, rtrim($this->dumper->dump($input, 1)));
}

public function getDateTimeData()
{
yield 'Date without subsecond precision' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03Z')],
'date: 2023-01-24T01:02:03+00:00',
];

yield 'Date with one digit for milliseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.4Z')],
'date: 2023-01-24T01:02:03.400+00:00',
];

yield 'Date with two digits for milliseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.45Z')],
'date: 2023-01-24T01:02:03.450+00:00',
];

yield 'Date with full milliseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.456Z')],
'date: 2023-01-24T01:02:03.456+00:00',
];

yield 'Date with four digits for microseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.4567Z')],
'date: 2023-01-24T01:02:03.456700+00:00',
];

yield 'Date with five digits for microseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.45678Z')],
'date: 2023-01-24T01:02:03.456780+00:00',
];

yield 'Date with full microseconds' => [
['date' => new \DateTimeImmutable('2023-01-24T01:02:03.456789Z')],
'date: 2023-01-24T01:02:03.456789+00:00',
];
}

private function assertSameData($expected, $actual)
{
$this->assertEquals($expected, $actual);
Expand Down
5 changes: 3 additions & 2 deletions src/Symfony/Component/Yaml/Tests/InlineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,10 @@ public function getTestsForDump()
/**
* @dataProvider getTimestampTests
*/
public function testParseTimestampAsUnixTimestampByDefault(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second)
public function testParseTimestampAsUnixTimestampByDefault(string $yaml, int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond)
{
$this->assertSame(gmmktime($hour, $minute, $second, $month, $day, $year), Inline::parse($yaml));
$expectedDate = (new \DateTimeImmutable($yaml))->format('U');
$this->assertSame($microsecond ? (float) "$expectedDate.$microsecond" : (int) $expectedDate, Inline::parse($yaml));
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/Symfony/Component/Yaml/Tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,15 @@ public function getInvalidBinaryData()
];
}

public function testParseDateWithSubseconds()
{
$yaml = <<<'EOT'
date: 2002-12-14T01:23:45.670000Z
EOT;

$this->assertSameData(['date' => 1039829025.67], $this->parser->parse($yaml));
}

public function testParseDateAsMappingValue()
{
$yaml = <<<'EOT'
Expand Down

0 comments on commit 8afb4c7

Please sign in to comment.