Affects: Spring Framework 5.3.16
The PR #28044 fixing the issue #28038 did cause a regression for winter daylight saving time
Problem: CronExpression fails to calculate properly next execution when running on the day of winter daylight saving time, just before DST is applied.
Here is a unit test case that you can add to CronExpressionTests#daylightSaving
to reproduce the problem :
cronExpression = CronExpression.parse("0 5 0 * * *");
last = ZonedDateTime.parse("2019-10-27T01:05+02:00[Europe/Paris]");
expected = ZonedDateTime.parse("2019-10-28T00:05+01:00[Europe/Paris]");
actual = cronExpression.next(last);
assertThat(actual).isNotNull();
assertThat(actual).isEqualTo(expected);
Please note that in the previous version 5.3.15 everything worked fine for that case
Comment From: poutsma
@guilroux Thank you for spotting this, without it users would have had invalid cron executions in October.
I have completely revised the way CronExpression
rolls forward temporal units, see https://github.com/spring-projects/spring-framework/commit/7e2106b850ea65866dc97d24d108c7fe1ea64c8c
Let me know if you see additional issues with this implementation, or have other concerns.
Comment From: mf81bln
@poutsma
We had an issue with Spring Boot 2.6.4 / Framework 5.3.16 on DST switch yesterday (March 27)
We're using a simple TaskScheduler
bean and a method annotated with @Scheduler(cron = "0 30 2 * * ?")
The execution was just skipped when time was jumping from 2am to 3am. I've tried to...
- add the time zone to the taskScheduler
@Bean
public TaskScheduler taskScheduler(final TaskSchedulerBuilder taskSchedulerBuilder)
{
return taskSchedulerBuilder
.poolSize(10)
.customizers(taskScheduler -> taskScheduler.setClock(Clock.system(ZoneId.of("Europe/Zurich"))))
.build();
}
- add zone property to
@Scheduled
@Scheduled(cron = "0 30 2 * * ?", zone = "Europe/Zurich")
public void run() { ... }
Both didn't work - tried it by resetting system time to 01:59:30am.
During debugging I found CronTrigger.nextExecutionTime()
always returning 2022-03-28T02:30:00+02:00
Is there anything else I have to configure so that the execution is not just skipped? Or do I need a custom handling for this?
I've checked documentation as well as previous issues / fixes and couldn't find any specifics on how to properly handle this scenario where an execution falls into the "skipped" time frame between 2am ... 3am
// edit: I've also tried it with the newest versions Spring Boot 2.6.5 / Framework 5.3.17 (because this was fixed) and resetting the time of my machine to March 27, 01:59:30 - the execution was skipped again
Comment From: poutsma
@mf81bln Please create a new issue instead of commenting on older, resolved issues. Feel free to ping me on said new issue.
FWIW, this works fine for me:
cronExpression = CronExpression.parse("0 30 2 * * ?"); // 01:59:30am
last = ZonedDateTime.parse("2022-03-26T01:59:30+01:00[Europe/Zurich]");
expected = ZonedDateTime.parse("2022-03-26T02:30:00+01:00[Europe/Zurich]");
actual = cronExpression.next(last);
assertThat(actual).isEqualTo(expected);
Comment From: mf81bln
@poutsma Sorry and thanks for your answer, I've created a new issue 👍
Your example works because it's running on March 26, switch to DST happened on Sunday, March 27