From a67ba35a7a2ed7ba565810bcd507aba72eefa582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Barto=C5=A1?= Date: Sat, 13 Jan 2024 18:39:11 +0100 Subject: [PATCH] ManagedScheduler: sets timezone specified by job to job start and end times --- CHANGELOG.md | 4 ++++ src/ManagedScheduler.php | 15 +++++++++++++-- tests/Unit/SimpleSchedulerTest.php | 29 ++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7088aab..9761e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - returns array of `JobSchedule` instead of an array of arrays - `RunSummary` - `getJobs()` -> `getJobSummaries()` +- `JobInfo` + - `getStart()->getTimeZone()` - returns timezone specified by the job +- `JobResult` + - `getEnd()->getTimeZone()` - returns timezone specified by the job - `JobExecutor` - `runJobs()` accepts list of `JobSchedule` grouped by seconds instead of list of ids - `runJobs()` returns `Generator` instead of `RunSummary` diff --git a/src/ManagedScheduler.php b/src/ManagedScheduler.php index ea5e588..592d3d0 100644 --- a/src/ManagedScheduler.php +++ b/src/ManagedScheduler.php @@ -3,6 +3,7 @@ namespace Orisai\Scheduler; use Closure; +use DateTimeImmutable; use Generator; use Orisai\Clock\Adapter\ClockAdapterFactory; use Orisai\Clock\Clock; @@ -208,7 +209,7 @@ private function runInternal($id, JobSchedule $jobSchedule, int $runSecond): arr $expression->getExpression(), $jobSchedule->getRepeatAfterSeconds(), $runSecond, - $this->clock->now(), + $this->getCurrentTime($jobSchedule), ); $lock = $this->lockFactory->createLock("Orisai.Scheduler.Job/$id"); @@ -240,7 +241,7 @@ private function runInternal($id, JobSchedule $jobSchedule, int $runSecond): arr $result = new JobResult( $expression, - $this->clock->now(), + $this->getCurrentTime($jobSchedule), $throwable === null ? JobResultState::done() : JobResultState::fail(), ); @@ -262,6 +263,16 @@ private function runInternal($id, JobSchedule $jobSchedule, int $runSecond): arr ]; } + private function getCurrentTime(JobSchedule $schedule): DateTimeImmutable + { + $now = $this->clock->now(); + $timezone = $schedule->getTimeZone(); + + return $timezone !== null + ? $now->setTimezone($timezone) + : $now; + } + /** * @param Closure(JobInfo, JobResult): void $callback */ diff --git a/tests/Unit/SimpleSchedulerTest.php b/tests/Unit/SimpleSchedulerTest.php index 9e307f3..76c6f21 100644 --- a/tests/Unit/SimpleSchedulerTest.php +++ b/tests/Unit/SimpleSchedulerTest.php @@ -5,6 +5,7 @@ use Closure; use Cron\CronExpression; use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; use ErrorException; use Exception; @@ -577,7 +578,7 @@ public function provideJobSummary(): Generator yield [new RunParameters(30), 30]; } - public function testTimeZone(): void + public function testTimeZoneExecution(): void { $defaultTz = new DateTimeZone('UTC'); $otherTz = new DateTimeZone('Europe/Prague'); @@ -624,6 +625,32 @@ static function () use (&$i2): void { self::assertSame(2, $i2); } + public function testTimeZoneInfo(): void + { + $defaultTz = new DateTimeZone('UTC'); + $otherTz = new DateTimeZone('Europe/Prague'); + $clock = new FrozenClock(0, $defaultTz); + + $scheduler = new SimpleScheduler(null, null, null, $clock); + $expression = new CronExpression('* * * * *'); + + $job = new CallbackJob(static function (): void { + // Noop + }); + $scheduler->addJob($job, $expression, null, 0, $otherTz); + + $summaries = $scheduler->run()->getJobSummaries(); + $summary = $summaries[0]; + + $start = $summary->getInfo()->getStart(); + self::assertEquals($otherTz, $start->getTimezone()); + self::assertSame('1970-01-01T01:00:00+01:00', $start->format(DateTimeInterface::ATOM)); + + $end = $summary->getResult()->getEnd(); + self::assertEquals($otherTz, $end->getTimezone()); + self::assertSame('1970-01-01T01:00:00+01:00', $end->format(DateTimeInterface::ATOM)); + } + public function testLockAlreadyAcquired(): void { $lockFactory = new TestLockFactory(new InMemoryStore(), false);