JST时间getSecondOfDay在DST切换日

时间:2016-06-21 07:22:03

标签: java timezone jodatime dst

在DST切换日试图获取午夜以来的秒数时,我从Joda Time得到了奇怪的行为。

我的代码:

public static void main(String[] args) {

    DateTimeZone timeZone = DateTimeZone.getDefault();
    System.out.println(timeZone);

    DateTimeFormatter dateFormatter = DateTimeFormat.shortDate();
    DateTimeFormatter dateTimeFormatter = DateTimeFormat.fullDateTime();
    LocalDate date = new LocalDate(2016, 10, 29);
    for (int i=0; i<3; i++) {

        System.out.println();
        System.out.println(dateFormatter.print(date) + ":");

        {
            DateTime instant = new DateTime(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), 1, 0, 0, timeZone);
            System.out.println(dateTimeFormatter.print(instant) + " // " + instant.getSecondOfDay() + " // " + instant.getZone().getOffset(instant));
        }

        {
            DateTime instant = new DateTime(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), 10, 0, 0, timeZone);
            System.out.println(dateTimeFormatter.print(instant) + " // " + instant.getSecondOfDay() + " // " + instant.getZone().getOffset(instant));
        }

        date = date.plusDays(1);
    }
}

输出:

Europe/Berlin

29.10.16:
Samstag, 29. Oktober 2016 01:00 Uhr MESZ // 3600 // 7200000
Samstag, 29. Oktober 2016 10:00 Uhr MESZ // 36000 // 7200000

30.10.16:
Sonntag, 30. Oktober 2016 01:00 Uhr MESZ // 3600 // 7200000
Sonntag, 30. Oktober 2016 10:00 Uhr MEZ // 36000 // 3600000

31.10.16:
Montag, 31. Oktober 2016 01:00 Uhr MEZ // 3600 // 3600000
Montag, 31. Oktober 2016 10:00 Uhr MEZ // 36000 // 3600000

(德语翻译:MEZ = CET,MESZ = CEST)

如您所见,10月30日是DST切换日。切换发生在凌晨2点到3点之间。如果我没有记错的话,夏令时是UTC + 2,冬令时是UTC + 1,所以凌晨3点,时钟回到凌晨2点。

现在这显然意味着2-3的重叠,但我的测试使用上午1点和上午10点,这应该是明确的。我预计10月30日凌晨1点CEST的瞬间从午夜开始是3600秒,而10月30日,欧洲中部时间上午10点的时刻是午夜(11小时)以来的39600秒。但getSecondOfDay()从午夜起返回10个小时。

我能想象的唯一含义(除了一个愚蠢的错误)是getSecondOfDay()实际上并没有返回自午夜以来的秒数,而是其他东西。但是,我在网上找到的每个例子似乎暗示它 返回自午夜以来的秒数。我也知道没有与DST相关的“午夜”重新定义。

为什么我会得到这些结果? getSecondOfDay()在这种情况下意味着什么? 我还应该做些什么才能获得自午夜以来的秒数?

1 个答案:

答案 0 :(得分:2)

字段SECOND_OF_DAY本质上是基于本地时间轴。这意味着,它不计算自午夜以来物理上经过的SI或POSIX秒数,但仅表示显示的标称时钟数在一个挂钟上,每天都有24小时/每天罢工,而忽略任何DST问题。或者另一种描述:想象一下,这个字段显示秒针在钟面上的位置。

但你可以以另一种方式确定实际经过的秒数。班级DateTime是一个瞬间,所以你可以先确定午夜的瞬间,然后是第二个瞬间,让我们在上午10点说。然后你应用这个表达式:

int elapsedSecondsSinceMidnight =
  Seconds.secondsBetween(instantMidnight, instant10AM).getSeconds();

请注意,如果由于DST切换而不存在本地时间,Joda-Time有时会导致异常为本地午夜创建一个瞬间(就像在巴西转移到夏令时一样)。所以请小心处理Joda-Time中的瞬间创建。