From 1b32d8d41d556ef5e2f8693489557d1bc74cd7cd Mon Sep 17 00:00:00 2001 From: zhaomeng Date: Thu, 4 Jun 2026 10:16:06 +0800 Subject: [PATCH 1/2] Include zone ID in CronTrigger's equals() and hashCode() implementations CronTrigger carries an optional ZoneId since 5.3 that affects nextExecution; however, prior to this commit, equals() and hashCode() only considered the cron expression. This commit ensures that CronTrigger instances with the same cron expression but different time zones are no longer considered equal. Closes gh-36871 Signed-off-by: zhaomeng --- .../scheduling/support/CronTrigger.java | 6 ++++-- .../scheduling/support/CronTriggerTests.java | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java b/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java index 5a055ce66ff..e596379f960 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java +++ b/spring-context/src/main/java/org/springframework/scheduling/support/CronTrigger.java @@ -19,6 +19,7 @@ package org.springframework.scheduling.support; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.Objects; import java.util.TimeZone; import org.jspecify.annotations.Nullable; @@ -145,12 +146,13 @@ public class CronTrigger implements Trigger { @Override public boolean equals(@Nullable Object other) { return (this == other || (other instanceof CronTrigger that && - this.expression.equals(that.expression))); + this.expression.equals(that.expression) && + Objects.equals(this.zoneId, that.zoneId))); } @Override public int hashCode() { - return this.expression.hashCode(); + return Objects.hash(this.expression, this.zoneId); } @Override diff --git a/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java b/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java index 2de519954da..e773770b2f0 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java @@ -16,6 +16,7 @@ package org.springframework.scheduling.support; +import java.time.ZoneId; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -746,6 +747,16 @@ class CronTriggerTests { assertThat(nextExecutionTime).isEqualTo(this.calendar.getTime()); } + @Test + void equalsAndHashCodeConsiderZoneId() { + String cron = "0 0 9 * * *"; + CronTrigger amsterdam = new CronTrigger(cron, ZoneId.of("Europe/Amsterdam")); + CronTrigger newYork = new CronTrigger(cron, ZoneId.of("America/New_York")); + + assertThat(amsterdam).isNotEqualTo(newYork); + assertThat(amsterdam).doesNotHaveSameHashCodeAs(newYork); + } + private static void roundup(Calendar calendar) { calendar.add(Calendar.SECOND, 1); From 6ca66afc7bfe7b3cfaa7646520cb4109a62c49e9 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:13:25 +0200 Subject: [PATCH 2/2] Polish contribution See gh-36871 --- .../scheduling/support/CronTriggerTests.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java b/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java index e773770b2f0..a341bd1f333 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/support/CronTriggerTests.java @@ -749,12 +749,16 @@ class CronTriggerTests { @Test void equalsAndHashCodeConsiderZoneId() { - String cron = "0 0 9 * * *"; - CronTrigger amsterdam = new CronTrigger(cron, ZoneId.of("Europe/Amsterdam")); - CronTrigger newYork = new CronTrigger(cron, ZoneId.of("America/New_York")); + String expression = "0 0 9 * * *"; + CronTrigger amsterdam1 = new CronTrigger(expression, ZoneId.of("Europe/Amsterdam")); + CronTrigger amsterdam2 = new CronTrigger(expression, ZoneId.of("Europe/Amsterdam")); + CronTrigger newYork = new CronTrigger(expression, ZoneId.of("America/New_York")); - assertThat(amsterdam).isNotEqualTo(newYork); - assertThat(amsterdam).doesNotHaveSameHashCodeAs(newYork); + assertThat(amsterdam1) + .isEqualTo(amsterdam2) + .hasSameHashCodeAs(amsterdam2) + .isNotEqualTo(newYork) + .doesNotHaveSameHashCodeAs(newYork); }