diff --git a/.upgradenotes/MDL-81894-1715921992633.yml b/.upgradenotes/MDL-81894-1715921992633.yml new file mode 100644 index 00000000000..5a933e3fc66 --- /dev/null +++ b/.upgradenotes/MDL-81894-1715921992633.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-81894 +notes: + core: + - message: >- + Use server timezone when constructing `\DateTimeImmutable` for the + system `\core\clock` implementation. + type: fixed diff --git a/lib/classes/system_clock.php b/lib/classes/system_clock.php index 32cee16898d..ba80e0e7814 100644 --- a/lib/classes/system_clock.php +++ b/lib/classes/system_clock.php @@ -24,10 +24,15 @@ namespace core; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class system_clock implements clock { + #[\Override] public function now(): \DateTimeImmutable { - return new \DateTimeImmutable(); + return new \DateTimeImmutable( + datetime: "now", + timezone: \core_date::get_server_timezone_object(), + ); } + #[\Override] public function time(): int { return $this->now()->getTimestamp(); } diff --git a/lib/tests/system_clock_test.php b/lib/tests/system_clock_test.php index c8f5555303d..1282e743b0c 100644 --- a/lib/tests/system_clock_test.php +++ b/lib/tests/system_clock_test.php @@ -26,6 +26,9 @@ namespace core; * @covers \core\system_clock */ final class system_clock_test extends \advanced_testcase { + /** + * Test that the now method returns a DateTimeImmutable object. + */ public function test_now(): void { $starttime = time(); @@ -34,4 +37,45 @@ final class system_clock_test extends \advanced_testcase { $this->assertInstanceOf(\DateTimeImmutable::class, $now); $this->assertGreaterThanOrEqual($starttime, $now->getTimestamp()); } + + /** + * Test that the time method returns a timestamp. + */ + public function test_time(): void { + $starttime = time(); + + $clock = new system_clock(); + $time = $clock->time(); + $this->assertGreaterThanOrEqual($starttime, $time); + } + + /** + * Test that the now method returns a DateTimeImmutable object in the server timezone. + * + * @dataProvider timezone_provider + * @param string $timezone + */ + public function test_now_timezone(string $timezone): void { + global $CFG; + $this->resetAfterTest(); + + $CFG->timezone = $timezone; + + $clock = new system_clock(); + $now = $clock->now(); + $this->assertEquals(\core_date::normalise_timezone($CFG->timezone), $now->getTimezone()->getName()); + } + + /** + * Data provider for the test_now_timezone method. + * + * @return array + */ + public static function timezone_provider(): array { + return [ + ['UTC'], + ['Europe/London'], + ['America/New_York'], + ]; + } }