使用 Joda Time 进行 DST 转换

Posted

技术标签:

【中文标题】使用 Joda Time 进行 DST 转换【英文标题】:DST transitions with Joda Time 【发布时间】:2012-09-12 11:39:56 【问题描述】:

我必须在 Java 应用程序中计算 DST 转换并查询 *** 我发现 joda time 有一个很好的 API 可以很容易地做到这一点。但实际上它给了我错误的结果(或者至少看起来是这样)。

我编写了一个示例程序来打印过去 5 年和未来 5 年的过渡。

public static void main(final String[] args)

    TimeZone javaZone = TimeZone.getDefault();
    DateTimeZone jodaTimezone = DateTimeZone.forTimeZone(javaZone);
    Calendar[] dstTransitions;
    DateTime jodaNewYear;
    int dstSavings;
    final Calendar calendar = Calendar.getInstance(javaZone);
    final DateFormat df = DateFormat.getDateTimeInstance();

    // use the correct timezone for displaying the date and time on console
    df.setTimeZone(javaZone);

    calendar.setTimeInMillis(System.currentTimeMillis());


    for (int i = -5; i < 5; i++)
    
        jodaNewYear = new DateTime(calendar.get(Calendar.YEAR) + i, 1, 1, 0, 0, 0, jodaTimezone);

        dstTransitions = new Calendar[2];
        dstTransitions[0] = Calendar.getInstance(javaZone);
        dstTransitions[0].setTimeInMillis(jodaTimezone.nextTransition(jodaNewYear.getMillis()));
        dstTransitions[1] = Calendar.getInstance(javaZone);
        dstTransitions[1].setTimeInMillis(jodaTimezone.nextTransition(dstTransitions[0].getTimeInMillis()));

        dstSavings = javaZone.getDSTSavings() / 1000;


        System.out.println("DST transitions for " + javaZone.getID() + " in " + jodaNewYear.getYear() + ":");
        System.out.println("To DST.....: " + df.format(dstTransitions[0].getTime()));
        System.out.println("From DST...: " + df.format(dstTransitions[1].getTime()));
        System.out.println("DST offset.: " + dstSavings + " sec");
        System.out.println("--------------------------------------------------------------------");
    

这在我的机器上给出了以下输出(摘录):

DST transitions for Europe/Berlin in 2007:
To DST.....: 25.03.2007 03:00:00
From DST...: 28.10.2007 02:00:00
DST offset.: 3600 sec
--------------------------------------------------------------------
DST transitions for Europe/Berlin in 2008:
To DST.....: 30.03.2008 03:00:00
From DST...: 26.10.2008 02:00:00
DST offset.: 3600 sec
--------------------------------------------------------------------
DST transitions for Europe/Berlin in 2009:
To DST.....: 29.03.2009 03:00:00
From DST...: 25.10.2009 02:00:00
DST offset.: 3600 sec
--------------------------------------------------------------------
DST transitions for Europe/Berlin in 2010:
To DST.....: 28.03.2010 03:00:00
From DST...: 31.10.2010 02:00:00
DST offset.: 3600 sec
--------------------------------------------------------------------
DST transitions for Europe/Berlin in 2011:
To DST.....: 27.03.2011 03:00:00
From DST...: 30.10.2011 02:00:00
DST offset.: 3600 sec
--------------------------------------------------------------------
DST transitions for Europe/Berlin in 2012:
To DST.....: 25.03.2012 03:00:00
From DST...: 28.10.2012 02:00:00
DST offset.: 3600 sec

看起来还不错,但我对时代有疑问。实际上,向 DST 的过渡发生在 3 月的最后一个星期日凌晨 2:00,而向后过渡发生在 10 月的最后一个星期日凌晨 3:00。因此,joda 过渡的时间似乎是错误的。

我对 joda API 完全陌生,所以我可能忽略了一些东西。可能的实际问题是:如何确定正确的过渡时间?

问候

塞巴斯蒂安

【问题讨论】:

【参考方案1】:

过渡时存在不连续性。 25.03.12 02:0025.03.12 03:00 是同一时刻,反之亦然在 10 月,除了从 02:00 到 03:00 小时重复,情况更加复杂。

看起来 Joda 正在为您提供过渡“后期”方面的时间——即过渡发生后的时间。要找到过渡“之前”的时间,请按 DST 偏移量进行调整。

【讨论】:

这仅适用于 10 月的过渡。对于 3 月的过渡,结果是凌晨 1:00。 好的。我实际上解决了我的情况。在欧洲/柏林时区,根据 Java 的 Calendar 类,三月最后一个星期日的凌晨 2:00:00 不存在。在用 joda time 计算转换时,如上所述,我得到 3:00:00 am。但是当我只减去一毫秒时,我会得到 1:59:59.999。 没错。我对那个过渡的回答有点不清楚。

以上是关于使用 Joda Time 进行 DST 转换的主要内容,如果未能解决你的问题,请参考以下文章

JODA 夏令时转换

org.joda.time |夏令时 (DST) 和本地时区偏移

如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime

无法使用 Joda Time API 将日期转换为 UTC [关闭]

使用 joda time 将一个时区转换为另一个时区

Scala,使用 play 2.5 将 joda.LocalDateTime 转换为 json