19

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

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

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

4

2 回答 2

34

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,您可以使用ZoneRulesnextTransitionpreviousTransition方法获得相同的信息。

于 2009-09-19T21:00:41.867 回答
4

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 教程:解释如何使用 java.time 的日期时间。

于 2019-06-17T09:54:18.180 回答