在 Java 中获取时区的夏令时转换日期

Posted

技术标签:

【中文标题】在 Java 中获取时区的夏令时转换日期【英文标题】:Get Daylight Saving Transition Dates For Time Zones in Java 【发布时间】:2021-03-18 12:22:38 【问题描述】:

我想知道用 Java 最简单的方法来获取未来夏令时将发生变化的日期列表。

执行此操作的一种相当不雅的方法是简单地迭代数年的天数,并针对 TimeZone.inDaylightTime() 对其进行测试。这会起作用,而且我不担心效率,因为它只需要在我的应用程序每次启动时运行,但我想知道是否有更简单的方法。

如果您想知道我为什么要这样做,那是因为我有一个 javascript 应用程序需要处理包含 UTC 时间戳的第三方数据。我想要一种在客户端从 GMT 转换为 EST 的可靠方法。请参阅Javascript -- Unix Time to Specific Time Zone 我已经编写了一些 javascript 可以做到这一点,但我想从服务器获取精确的转换日期。

【问题讨论】:

看到这个问题:***.com/questions/581581/… 【参考方案1】:

Joda Time (一如既往)由于DateTimeZone.nextTransition 方法使这变得非常容易。例如:

import org.joda.time.*;
import org.joda.time.format.*;

public class Test
    
    public static void main(String[] args)
    
        DateTimeZone zone = DateTimeZone.forID("Europe/London");        
        DateTimeFormatter format = DateTimeFormat.mediumDateTime();

        long current = System.currentTimeMillis();
        for (int i=0; i < 100; i++)
        
            long next = zone.nextTransition(current);
            if (current == next)
            
                break;
            
            System.out.println (format.print(next) + " Into DST? " 
                                + !zone.isStandardOffset(next));
            current = next;
        
    

输出:

2009 年 10 月 25 日 01:00:00 进入夏令时?错误的 2010 年 3 月 28 日 02:00:00 进入夏令时?真的 2010 年 10 月 31 日 01:00:00 进入夏令时?错误的 2011 年 3 月 27 日 02:00:00 进入夏令时?真的 2011 年 10 月 30 日 01:00:00 进入夏令时?错误的 2012 年 3 月 25 日 02:00:00 进入夏令时?真的 2012 年 10 月 28 日 01:00:00 进入夏令时?错误的 2013 年 3 月 31 日 02:00:00 进入夏令时?真的 2013 年 10 月 27 日 01:00:00 进入夏令时?错误的 2014 年 3 月 30 日 02:00:00 进入夏令时?真的 2014 年 10 月 26 日 01:00:00 进入夏令时?错误的 2015 年 3 月 29 日 02:00:00 进入夏令时?真的 2015 年 10 月 25 日 01:00:00 进入夏令时?错误的 ...

使用 Java 8,您可以使用 ZoneRules 及其 nextTransitionpreviousTransition 方法获得相同的信息。

【讨论】:

+1 表示“样本来了”的想法(当然还有其他答案) 当然,预测这么远是相当投机的。美国最近修改了 DST 日期,并且可能会再次修改。 今年第一个 DST 过渡日期是 2010 年 3 月 14 日(发生在几天前)。但是您的脚本指定了 28-Mar-2010。我错过了什么吗? @Silence:现在是伦敦的 3 月 28 日,这是代码中指定的时区。不是每个人都在美国... @bluelurker:在 Java 8 中,您可以使用 ZoneRules.nextTransitionZoneRules.previousTransition。我在答案中编辑了一个链接。【参考方案2】:

java.time

现代答案使用 java.time,现代 Java 日期和时间 API。

    ZoneId zone = ZoneId.of("Europe/London");
    ZoneRules rules = zone.getRules();
    ZonedDateTime now = ZonedDateTime.now(zone);
    ZoneOffsetTransition transition = rules.nextTransition(now.toInstant());
    Instant max = now.plusYears(15).toInstant();
    while (transition != null && transition.getInstant().isBefore(max)) 
        System.out.println(transition);
        transition = rules.nextTransition(transition.getInstant());
    

输出,缩写:

Transition[Overlap at 2019-10-27T02:00+01:00 to Z]
Transition[Gap at 2020-03-29T01:00Z to +01:00]
Transition[Overlap at 2020-10-25T02:00+01:00 to Z]
Transition[Gap at 2021-03-28T01:00Z to +01:00]
Transition[Overlap at 2021-10-31T02:00+01:00 to Z]
Transition[Gap at 2022-03-27T01:00Z to +01:00]
Transition[Overlap at 2022-10-30T02:00+01:00 to Z]
(cut)
Transition[Overlap at 2033-10-30T02:00+01:00 to Z]
Transition[Gap at 2034-03-26T01:00Z to +01:00]

不过,我不会对数据过于信任。我不确定英国脱欧后(以及欧盟可能在 2021 年放弃夏令时 (DST) 之后)英国的时间会发生什么变化。

链接: Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

以上是关于在 Java 中获取时区的夏令时转换日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Dynamics CRM 中获取时区的夏令时开始和结束?

如何获取另一个时区的夏令时状态

Calendar日期类详解SimpleDateFormat时区Date夏令时常用方法,日期差获取当前时间

带有时区和夏令时的纪元的日期和时间(以秒为单位)

澳大利亚/墨尔本时区的 Java 8 中的日期时间夏令时问题

来自第三方设备的时区