Skip to content

Commit

Permalink
Merge pull request #19 from Elemecca/create-from-format-unix
Browse files Browse the repository at this point in the history
  • Loading branch information
asprega authored Jun 20, 2022
2 parents bf0511d + 4e05a86 commit 890d181
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 14 deletions.
30 changes: 20 additions & 10 deletions src/ClockMock.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,26 @@ private static function mock_date_create(): callable
private static function mock_date_create_from_format(): callable
{
return function ($format, $datetime, DateTimeZone $timezone = null) {
$dateTimeObject = \DateTime::createFromFormat($format, $datetime, $timezone);

$parsedDate = date_parse($datetime);

return $dateTimeObject->setTime(
$parsedDate['hour'] === false ? idate('H') : $parsedDate['hour'],
$parsedDate['minute'] === false ? idate('i') : $parsedDate['minute'],
$parsedDate['second'] === false ? idate('s') : $parsedDate['second'],
$parsedDate['fraction'] === false ? (int) date('u') : $parsedDate['fraction'],
);
$dateTimeObject = \DateTime::createFromFormat($format, (string) $datetime, $timezone);

// If the format doesn't include any time parts `createFromFormat` uses the current time, not all zeroes.
// In that case the un-mocked call above will use the real time, not the mocked time.
// This uses `date_parse_from_format` to detect whether the format includes time parts and,
// if so, replaces the time of the result with the frozen time.
// `date_parse_from_format` returns false for all time parts if no time parts are included in the format,
// but if the format includes at least one time part all time parts not included become zero instead.
$parsedDate = date_parse_from_format($format, (string) $datetime);
if ($parsedDate['hour'] === false) {
$frozen = ClockMock::getFrozenDateTime();
return $dateTimeObject->setTime(
(int) $frozen->format('H'),
(int) $frozen->format('i'),
(int) $frozen->format('s'),
(int) $frozen->format('u'),
);
} else {
return $dateTimeObject;
}
};
}

Expand Down
29 changes: 25 additions & 4 deletions tests/ClockMockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function test_DateTimeImmutable_createFromFormat()
// Verification: when not provided with a time, createFromFormat should use current time.
$this->assertSame('2022-05-28 12:13:14', $dateTimeFromFormat->format('Y-m-d H:i:s'));
}

public function test_DateTime_constructor_with_absolute_mocked_date()
{
ClockMock::freeze($fakeNow = new \DateTime('1986-06-05'));
Expand Down Expand Up @@ -107,14 +107,35 @@ public function test_DateTime_constructor_with_relative_mocked_date_without_micr
$this->assertEquals($juneFifth1986, new \DateTime('1986-06-05'));
}

public function test_DateTime_createFromFormat()
public function test_DateTime_createFromFormat_with_time()
{
ClockMock::freeze(new \DateTimeImmutable('1986-06-05 12:13:14'));
ClockMock::freeze(new \DateTimeImmutable('1986-06-05 12:13:14.168432'));

$dateTimeFromFormat = \DateTime::createFromFormat('Y-m-d i', '2022-05-28 24');

$this->assertSame('2022-05-28 00:24:00.000000', $dateTimeFromFormat->format('Y-m-d H:i:s.u'));
}

public function test_DateTime_createFromFormat_without_time()
{
ClockMock::freeze(new \DateTimeImmutable('1986-06-05 12:13:14.168432'));

$dateTimeFromFormat = \DateTime::createFromFormat('Y-m-d', '2022-05-28');

// Verification: when not provided with a time, createFromFormat should use current time.
$this->assertSame('2022-05-28 12:13:14', $dateTimeFromFormat->format('Y-m-d H:i:s'));
$this->assertSame('2022-05-28 12:13:14.168432', $dateTimeFromFormat->format('Y-m-d H:i:s.u'));
}

public function test_DateTime_createFromFormat_unix()
{
ClockMock::freeze(new \DateTimeImmutable('1986-06-05 12:13:14.168432'));

// this strange pattern occurs in Symfony 4.4.42
// Symfony\Component\HttpFoundation\ResponseHeaderBag.php:306
$dateTimeFromFormat = \DateTime::createFromFormat('U', time());

// time() is integer seconds, so the microseconds get rounded off
$this->assertSame('1986-06-05 12:13:14.000000', $dateTimeFromFormat->format('Y-m-d H:i:s.u'));
}

public function test_date()
Expand Down

0 comments on commit 890d181

Please sign in to comment.