关于java:支持跨时区和夏令时更改的重复事件

Supporting recurring events across time zones and daylight savings changes

建立了一个基本系统,允许用户在某个日期/时间安排与A、B、C个人的会议。

我想检查一下我们的解决方案是否能在DST变更中起作用。

这两个关键类是:

  • User—持有用户的ZoneId,所以Europe/ParisAsia/Tokyo等。
  • Event持有预定事件的LocalDateTime,如事件创建时用户的2018-05-04T10:00:00.000ZoneId,如Europe/Paris

然后我们将事件放入调度程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.scheduling.TaskScheduler;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public class MyScheduler {

    private final TaskScheduler executor;

    ...

    public void schedule(Event event) {
        ...
        ZonedDateTime scheduledAt = ZonedDateTime.of(event.getScheduledAt(), event.getScheduledAtTimeZone());
        if (scheduledAt.isAfter(ZonedDateTime.now(ZoneId.systemDefault()))) {
            executor.schedule(task, Date.from(scheduledAt.toInstant()));
        }
    }
}

如果我是正确的,那么上面的代码应该启动设置为星期五上午10点的事件Europe/Paris,不管时钟是UTC+1还是UTC+2。

上面的方法看起来正常吗?

我还注意到,ZonedDateTime类除了时间和区域(如2018-05-02T20:46:03.002+01:00[Europe/London]外,还有一个偏移量。(我能想到)保持偏移量的唯一原因是知道用户是否在夏令时创建了事件。

在这种情况下,存储偏移量的系统有什么好处吗,或者我们只使用本地事件时间和创建偏移量的区域吗?


我能想到的唯一真正的问题是,在秋天,当时钟向后移动时,事件发生在角落的情况下,那么LocalDateTime即使知道该区域也可能模糊不清。

Instant通常被推荐用于时区中性点,因此,除非严格要求了解创建事件的时区,否则我将使用它。即使这是一个要求,因为你仍然可以把ZoneId放在它旁边。它还可以使您的代码更简单一些。另一个明智的选择是在预定时间内使用ZonedDateTime;它对我的吸引力较小。