-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Daylight saving time fix #48363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Daylight saving time fix #48363
Changes from all commits
0bc168c
5a8e583
371b2b9
bdfde03
1a52d1e
c9246a3
bc34fee
4da9f6a
42b2c88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
| import java.time.DayOfWeek; | ||
| import java.time.Duration; | ||
| import java.time.ZonedDateTime; | ||
| import java.time.ZoneOffset; | ||
| import java.util.List; | ||
|
|
||
| import com.azure.spring.cloud.feature.management.implementation.models.RecurrencePattern; | ||
|
|
@@ -98,8 +99,26 @@ private static OccurrenceInfo getWeeklyPreviousOccurrence(TimeWindowFilterSettin | |
|
|
||
| final long numberOfInterval = Duration.between(firstDayOfFirstWeek, now).toSeconds() | ||
| / Duration.ofDays((long) interval * RecurrenceConstants.DAYS_PER_WEEK).toSeconds(); | ||
| final ZonedDateTime firstDayOfMostRecentOccurringWeek = firstDayOfFirstWeek.plusDays( | ||
| ZonedDateTime firstDayOfMostRecentOccurringWeek = firstDayOfFirstWeek.plusDays( | ||
| numberOfInterval * (interval * RecurrenceConstants.DAYS_PER_WEEK)); | ||
|
|
||
|
Comment on lines
100
to
+104
|
||
| // Handle DST transitions: If the calculated week start has a fixed offset (ZoneOffset) | ||
| // and 'now' has a region zone, check if they represent the same geographic location. | ||
| // We do this by checking if the fixed offset matches what the region zone's offset | ||
| // was at the *original start time*. If it matches, they're in the same timezone, | ||
| // and we should convert to the region zone for DST-aware comparisons. | ||
| if (firstDayOfMostRecentOccurringWeek.getZone() instanceof ZoneOffset | ||
| && !(now.getZone() instanceof ZoneOffset)) { | ||
| // Check if the fixed offset matches the region zone's offset at the *start* instant | ||
| // (not at firstDayOfMostRecentOccurringWeek's instant, which might have crossed DST) | ||
| ZoneOffset offsetAtStart = now.getZone().getRules().getOffset(start.toInstant()); | ||
| if (start.getOffset().equals(offsetAtStart)) { | ||
| // Same geographic location, convert to region zone for DST-aware comparisons | ||
| firstDayOfMostRecentOccurringWeek = firstDayOfMostRecentOccurringWeek | ||
| .withZoneSameLocal(now.getZone()); | ||
| } | ||
| } | ||
mrm9084 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| final List<DayOfWeek> sortedDaysOfWeek = TimeWindowUtils.sortDaysOfWeek(pattern.getDaysOfWeek(), pattern.getFirstDayOfWeek()); | ||
| final int maxDayOffset = TimeWindowUtils.getPassedWeekDays(sortedDaysOfWeek.get(sortedDaysOfWeek.size() - 1), pattern.getFirstDayOfWeek()); | ||
| final int minDayOffset = TimeWindowUtils.getPassedWeekDays(sortedDaysOfWeek.get(0), pattern.getFirstDayOfWeek()); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
numberOfIntervalis computed usingDuration.between(...).toSeconds() / Duration.ofDays(...).toSeconds(). Around DST transitions this can undercount by 1 when the local wall-clock time matches the weekly boundary but the underlying instants differ by +/-1 hour (e.g., 3 weeks minus 1 hour after spring-forward). This means the “most recent occurring week” can be shifted back a week, which defeats the DST fix.Consider computing the interval count using calendar-based units (e.g.,
ChronoUnit.DAYS/WEEKSbetweenLocalDates after aligningnow/firstDayOfFirstWeekto the same intended zone), instead of seconds-based duration division.