Skip to content

Commit d5b17c5

Browse files
committed
Fixes #37: support non canonical timezones in mocks
1 parent dda085e commit d5b17c5

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

src/DateTimeMock/DateTimeMock.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ public function __construct(?string $datetime = 'now', ?DateTimeZone $timezone =
2828
if ($timezone !== null && !$isDateTimeStringRelative) {
2929
// When there's a timezone and the provided date is absolute, the timestamp must be calculated with that
3030
// specific timezone in order to mimic behavior of the original \DateTime (which does not modify time).
31-
$this->setTimestamp(
32-
strtotime(
33-
"$datetime {$timezone->getName()}",
34-
ClockMock::getFrozenDateTime()->getTimestamp()
35-
)
36-
);
31+
$timestamp = strtotime("$datetime {$timezone->getName()}", ClockMock::getFrozenDateTime()->getTimestamp());
32+
if ($timestamp === false) {
33+
// Some non-canonical timezone names (e.g. US/Eastern) are not supported by `strtotime`. In these cases,
34+
// apply the same workaround by using the offset in seconds.
35+
$offset = -$timezone->getOffset(new \DateTime('now'));
36+
$timestamp = strtotime("$datetime $offset seconds", ClockMock::getFrozenDateTime()->getTimestamp());
37+
}
38+
39+
$this->setTimestamp($timestamp);
3740
} else {
3841
$this->setTimestamp(strtotime($datetime, ClockMock::getFrozenDateTime()->getTimestamp()));
3942
}

tests/ClockMockTest.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function test_DateTime_constructor_with_absolute_mocked_date()
104104
/**
105105
* @see https://github.com/slope-it/clock-mock/issues/26
106106
*/
107-
public function test_DateTime_constructor_with_absolute_date_and_timezone()
107+
public function test_DateTime_constructor_with_absolute_date_and_canonical_timezone()
108108
{
109109
// The mocked date, either aboslute or relative, is irrelevant for this test. Having a mocked date is enough.
110110
ClockMock::freeze(new \DateTime('now'));
@@ -119,6 +119,25 @@ public function test_DateTime_constructor_with_absolute_date_and_timezone()
119119
$this->assertSame('1986-06-05 12:13:14', $absoluteDateTimeWithTimezone->format('Y-m-d H:i:s'));
120120
}
121121

122+
/**
123+
* @see https://github.com/slope-it/clock-mock/issues/37
124+
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
125+
*/
126+
public function test_DateTime_constructor_with_absolute_date_and_non_canonical_timezone()
127+
{
128+
// The mocked date, either aboslute or relative, is irrelevant for this test. Having a mocked date is enough.
129+
ClockMock::freeze(new \DateTime('now'));
130+
131+
$absoluteDateTimeWithTimezone = new \DateTime(
132+
'1986-06-05 12:13:14',
133+
$usEasternTimezone = new \DateTimeZone('US/Eastern')
134+
);
135+
136+
// Verification: when date is absolute and timezone is specified, the mocked clock should have no effect.
137+
$this->assertEquals($usEasternTimezone, $absoluteDateTimeWithTimezone->getTimezone());
138+
$this->assertSame('1986-06-05 12:13:14', $absoluteDateTimeWithTimezone->format('Y-m-d H:i:s'));
139+
}
140+
122141
/**
123142
* @see https://github.com/slope-it/clock-mock/issues/31
124143
*/

0 commit comments

Comments
 (0)