diff --git a/src/Symfony/Component/Clock/CHANGELOG.md b/src/Symfony/Component/Clock/CHANGELOG.md index 1a9ffc835f697..254e71c794b5e 100644 --- a/src/Symfony/Component/Clock/CHANGELOG.md +++ b/src/Symfony/Component/Clock/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Throw `DateMalformedStringException`/`DateInvalidTimeZoneException` when appropriate + * Add `$modifier` argument to the `now()` helper 6.3 --- diff --git a/src/Symfony/Component/Clock/Resources/now.php b/src/Symfony/Component/Clock/Resources/now.php index 9a88efbe4d43d..d4999fd922ad5 100644 --- a/src/Symfony/Component/Clock/Resources/now.php +++ b/src/Symfony/Component/Clock/Resources/now.php @@ -13,13 +13,29 @@ if (!\function_exists(now::class)) { /** - * Returns the current time as a DateTimeImmutable. - * - * Note that you should prefer injecting a ClockInterface or using - * ClockAwareTrait when possible instead of using this function. + * @throws \DateMalformedStringException When the modifier is invalid */ - function now(): \DateTimeImmutable + function now(string $modifier = null): \DateTimeImmutable { - return Clock::get()->now(); + if (null === $modifier || 'now' === $modifier) { + return Clock::get()->now(); + } + + $now = Clock::get()->now(); + + if (\PHP_VERSION_ID < 80300) { + try { + $tz = (new \DateTimeImmutable($modifier, $now->getTimezone()))->getTimezone(); + } catch (\Exception $e) { + throw new \DateMalformedStringException($e->getMessage(), $e->getCode(), $e); + } + $now = $now->setTimezone($tz); + + return @$now->modify($modifier) ?: throw new \DateMalformedStringException(error_get_last()['message'] ?? sprintf('Invalid date modifier "%s".', $modifier)); + } + + $tz = (new \DateTimeImmutable($modifier, $now->getTimezone()))->getTimezone(); + + return $now->setTimezone($tz)->modify($modifier); } } diff --git a/src/Symfony/Component/Clock/Tests/ClockTest.php b/src/Symfony/Component/Clock/Tests/ClockTest.php index e88ade2558777..bf71543d3ce18 100644 --- a/src/Symfony/Component/Clock/Tests/ClockTest.php +++ b/src/Symfony/Component/Clock/Tests/ClockTest.php @@ -39,6 +39,19 @@ public function testNativeClock() $this->assertInstanceOf(NativeClock::class, Clock::get()); } + public function testNowModifier() + { + $this->assertSame('2023-08-14', now('2023-08-14')->format('Y-m-d')); + $this->assertSame('Europe/Paris', now('Europe/Paris')->getTimezone()->getName()); + $this->assertSame('UTC', now('UTC')->getTimezone()->getName()); + } + + public function testInvalidNowModifier() + { + $this->expectException(\DateMalformedStringException::class); + now('invalid date'); + } + public function testMockClockDisable() { $this->assertInstanceOf(NativeClock::class, Clock::get()); @@ -52,6 +65,7 @@ public function testMockClockFreeze() self::mockTime(new \DateTimeImmutable('2021-12-19')); $this->assertSame('2021-12-19', now()->format('Y-m-d')); + $this->assertSame('2021-12-20', now('+1 days')->format('Y-m-d')); self::mockTime('+1 days'); $this->assertSame('2021-12-20', now()->format('Y-m-d'));