如何在不同时区的特定时间执行作业

how to execute a job at a certain time in a different timezone

假设我在英国夏令时,即英国夏令时,并且我想根据 US/Eastern 时区在 19.30 执行工作,那么我该如何实现。

我试过的示例代码,

Instant now = Instant.now();
LocalDateTime localTimeNow = LocalDateTime.ofInstant(now, ZoneOffset.systemDefault());
//if BST then use "Europe/London" 
//if US/Eastern then use "America/New_York" 
// For EST also use "America/New_York"
// If GB-Eire then use "Europe/London"
ZonedDateTime bsTime = now.atZone(ZoneId.of("Europe/London"));

ZonedDateTime nyAmerica = now.atZone(ZoneId.of("America/New_York"));

// Lets calculate the difference between 2 timezones
// Between London and EST
long timeDiff = ChronoUnit.MILLIS.between(bsTime, nyAmerica);
System.out.println("timeDiff - " + timeDiff);

int minutes = (int) ((timeDiff / 1000) / 60);

System.out.println("Time diff bet London and EST - " + minutes + " minutes");

long diff = Duration.between(bsTime, nyAmerica).getSeconds();
int mins = (int) (diff / 60);
System.out.println("Time diff bet London and EST - " + mins + " minutes");

在这两种情况下它都给了我零。

我想要的是我必须使用此延迟将其传递给执行程序服务,如下所示,

executor.schedule(myRunnable, delay, TimeUnit.SECONDS);

因此,即使我在英国,根据 US/Eastern.

,该工作也应在 19.30 执行

还有一些缩写如 EST、BST 不是有效的 ZoneId。 那么,当我的时区采用缩写格式(如 EST 或 BST 等)时,我该如何处理这些情况?

您可以尝试使用 Spring Boot Quartz Scheduler
参考:https://www.callicoder.com/spring-boot-quartz-scheduler-email-scheduling-example/

更新: 下面的原始答案显示了如何计算当地时间以开始必须在一天中的特定时间 运行不同的时区。

如果你只是想计算到那个时间要等多久,可以更简单,不涉及当地时区。

LocalTime jobStartTime = LocalTime.of(19, 30);
ZoneId jobZone = ZoneId.of("America/New_York");

ZonedDateTime now = ZonedDateTime.now(jobZone);
ZonedDateTime jobDateTime = now.with(jobStartTime);
if (jobDateTime.isBefore(now))
    jobDateTime.plusDays(1);
long delay = ChronoUnit.MILLIS.between(now, jobDateTime);

System.out.println("now         = " + now);
System.out.println("jobDateTime = " + jobDateTime);
System.out.println("delay       = " + delay + "  =  " + Duration.ofMillis(delay));

输出

now         = 2020-07-17T08:18:45.482028800-04:00[America/New_York]
jobDateTime = 2020-07-17T19:30-04:00[America/New_York]
delay       = 40274517  =  PT11H11M14.517S

原答案

now2020-07-17 07:57:45 Z
在伦敦是 2020-07-17 08:57:45 +01:00
在纽约是 2020-07-17 03:57:45 -04:00.

伦敦和纽约的时差是多少?
0 秒,因为它们是同一时间

问题中的代码不计算时间 19:30。相反,它会尝试计算 现在 的时区差异,但由于夏令时,7:30 下午的时区差异可能是 不同,所以方法是错误的

如果您在伦敦,并且需要知道下一次19:30在纽约的时间,请这样做:

Instant now = Instant.now();
ZoneId localZone = ZoneId.of("Europe/London");
ZoneId remoteZone = ZoneId.of("America/New_York");
System.out.println("now             = " + now);

ZonedDateTime remoteNow = now.atZone(remoteZone);
LocalDate remoteDate = remoteNow.toLocalDate();
LocalTime remoteTime = LocalTime.of(19, 30);
if (remoteNow.toLocalTime().isAfter(remoteTime))
    remoteDate = remoteDate.plusDays(1);
ZonedDateTime remoteStartTime = ZonedDateTime.of(remoteDate, remoteTime, remoteZone);
System.out.println("remoteNow       = " + remoteNow);
System.out.println("remoteStartTime = " + remoteStartTime);

ZonedDateTime localStartTime = remoteStartTime.withZoneSameInstant(localZone);
System.out.println("localNow        = " + now.atZone(localZone));
System.out.println("localStartTime  = " + localStartTime);

输出

now             = 2020-07-17T07:57:45.206007800Z
remoteNow       = 2020-07-17T03:57:45.206007800-04:00[America/New_York]
remoteStartTime = 2020-07-17T19:30-04:00[America/New_York]
localNow        = 2020-07-17T08:57:45.206007800+01:00[Europe/London]
localStartTime  = 2020-07-18T00:30+01:00[Europe/London]

因此,在计算机上 运行 宁英国时区,美国东部的下一个 7:30 下午时间是今晚午夜半点。