Skip to content

Commit 77a248b

Browse files
authored
Fix createFromFormat with Unix timestamp format 'U' (#502)
The 3.3.2 fix for respecting testNow in createFromFormat incorrectly applied testNow values when using the Unix timestamp format 'U'. Since 'U' sets all date/time components from the Unix timestamp value, testNow should not be applied. This caused createFromFormat('U', '0') to return the current test time instead of the Unix epoch (1970-01-01 00:00:00). The fix adds 'U' to the list of format specifiers that should skip the testNow application, similar to '!' and '|'.
1 parent e425685 commit 77a248b

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

src/Chronos.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,9 +694,11 @@ protected static function applyTestNowToMissingComponents(
694694
$hasMicro = (bool)array_intersect($formatChars, ['u', 'v']);
695695

696696
// If the format includes '!' or '|', PHP resets unspecified components to Unix epoch or zero
697-
// In that case, we should not override with testNow
697+
// If 'U' is present, all components are set from the Unix timestamp
698+
// In these cases, we should not override with testNow
698699
$hasReset = in_array('!', $formatChars, true) || in_array('|', $formatChars, true);
699-
if ($hasReset) {
700+
$hasUnixTimestamp = in_array('U', $formatChars, true);
701+
if ($hasReset || $hasUnixTimestamp) {
700702
return $dateTime;
701703
}
702704

tests/TestCase/DateTime/CreateFromFormatTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,22 @@ public function testCreateFromFormatWithTestNowMicroseconds()
111111
$this->assertSame(123456, $d->micro);
112112
}
113113

114+
public function testCreateFromFormatWithTestNowUnixTimestamp()
115+
{
116+
// Unix timestamp ('U' format) sets all components, should not use testNow
117+
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
118+
$d = Chronos::createFromFormat('U', '0');
119+
$this->assertDateTime($d, 1970, 1, 1, 0, 0, 0);
120+
}
121+
122+
public function testCreateFromFormatWithTestNowNegativeUnixTimestamp()
123+
{
124+
// Negative Unix timestamp should also not use testNow
125+
Chronos::setTestNow(new Chronos('2020-12-01 14:30:45'));
126+
$d = Chronos::createFromFormat('U', '-1000');
127+
$this->assertDateTime($d, 1969, 12, 31, 23, 43, 20);
128+
}
129+
114130
public function testCreateFromFormatWithTimezoneString()
115131
{
116132
$d = Chronos::createFromFormat('Y-m-d H:i:s', '1975-05-21 22:32:11', 'Europe/London');

0 commit comments

Comments
 (0)