Fix daylight saving issue in CronExpression
Closes gh-26830
This commit is contained in:
@@ -157,6 +157,11 @@ abstract class CronField {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static <T extends Temporal & Comparable<? super T>> T cast(Temporal temporal) {
|
||||
return (T) temporal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the type of cron field, i.e. seconds, minutes, hours,
|
||||
@@ -236,16 +241,17 @@ abstract class CronField {
|
||||
*/
|
||||
public <T extends Temporal & Comparable<? super T>> T elapseUntil(T temporal, int goal) {
|
||||
int current = get(temporal);
|
||||
ValueRange range = temporal.range(this.field);
|
||||
if (current < goal) {
|
||||
T result = this.field.getBaseUnit().addTo(temporal, goal - current);
|
||||
current = get(result);
|
||||
if (current > goal) { // can occur due to daylight saving, see gh-26744
|
||||
result = this.field.getBaseUnit().addTo(result, goal - current);
|
||||
if (range.isValidIntValue(goal)) {
|
||||
return cast(temporal.with(this.field, goal));
|
||||
}
|
||||
else {
|
||||
// goal is invalid, eg. 29th Feb, lets try to get as close as possible
|
||||
return this.field.getBaseUnit().addTo(temporal, goal - current);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
ValueRange range = temporal.range(this.field);
|
||||
long amount = goal + range.getMaximum() - current + 1 - range.getMinimum();
|
||||
return this.field.getBaseUnit().addTo(temporal, amount);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -326,12 +326,6 @@ final class QuartzCronField extends CronField {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Temporal & Comparable<? super T>> T cast(Temporal temporal) {
|
||||
return (T) temporal;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
|
||||
T result = adjust(temporal);
|
||||
|
||||
@@ -1276,6 +1276,14 @@ class CronExpressionTests {
|
||||
actual = cronExpression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
cronExpression = CronExpression.parse("0 10 2 * * *");
|
||||
|
||||
last = ZonedDateTime.parse("2013-03-31T01:09:00+01:00[Europe/Amsterdam]");
|
||||
expected = ZonedDateTime.parse("2013-04-01T02:10:00+02:00[Europe/Amsterdam]");
|
||||
actual = cronExpression.next(last);
|
||||
assertThat(actual).isNotNull();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -822,13 +822,13 @@ class CronTriggerTests {
|
||||
|
||||
// 2:00 AM on March 31, 2013: start of Daylight Saving Time for CET in 2013.
|
||||
// Setting up last completion:
|
||||
// - PST: Sun Mar 31 10:10:54 CEST 2013
|
||||
// - CET: Sun Mar 31 01:10:54 CET 2013
|
||||
// - PST: Sun Mar 31 10:09:54 CEST 2013
|
||||
// - CET: Sun Mar 31 01:09:54 CET 2013
|
||||
this.calendar.set(Calendar.DAY_OF_MONTH, 31);
|
||||
this.calendar.set(Calendar.MONTH, Calendar.MARCH);
|
||||
this.calendar.set(Calendar.YEAR, 2013);
|
||||
this.calendar.set(Calendar.HOUR_OF_DAY, 1);
|
||||
this.calendar.set(Calendar.MINUTE, 10); // changing to any minute from 0-9 causes the test to fail for CET.
|
||||
this.calendar.set(Calendar.MINUTE, 9);
|
||||
this.calendar.set(Calendar.SECOND, 54);
|
||||
Date lastCompletionTime = this.calendar.getTime();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user