【问题标题】:Java Calendar.roll over DST begin/end has incorrect valuesJava Calendar.roll over DST begin/end 的值不正确
【发布时间】:2016-02-23 03:24:27
【问题描述】:

当您尝试翻转 DST 开始或结束的日期时,会出现此问题。例如,我们可以使用“America/New_York”时区将 01/11/2015 设置为日历(EDT 更改为 EST 的那一天)并尝试滚动:

TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar cal = Calendar.getInstance(timeZone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
formatter.setTimeZone(timeZone);
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
for (int i = 0; i < 24; i++)
{
    cal.roll(Calendar.HOUR_OF_DAY, 1);
    System.out.println("Formatted  date: " + formatter.format(cal.getTime()));
}

这是结果:
...
格式化日期:2015.11.01 22:08:32 EST
格式化日期:2015.11.01 23:08:32 EST
格式化日期:2015.11.01 01:08:32 EDT
格式化日期:2015.11.01 01:08:32 EST
格式化日期:2015.11.01 02:08:32 EST
...

【问题讨论】:

    标签: java calendar timezone


    【解决方案1】:

    看看roll javadoc。

    Calendar 上的这个默认实现只是重复调用滚动一个单位的 roll() 版本。 这可能并不总是正确的。

    Calendar.roll javadoc

    如果您改用 Calendar.add 并从 10 月 31 日开始,您将看到正确的输出 --

    Formatted  date: 2015.10.31 21:33:31 EDT
    Formatted  date: 2015.10.31 22:33:31 EDT
    Formatted  date: 2015.10.31 23:33:31 EDT
    Formatted  date: 2015.11.01 00:33:31 EDT
    Formatted  date: 2015.11.01 01:33:31 EDT
    Formatted  date: 2015.11.01 01:33:31 EST
    Formatted  date: 2015.11.01 02:33:31 EST
    Formatted  date: 2015.11.01 03:33:31 EST
    

    由于您必须使用roll,因此添加一些自定义逻辑来确定 EST 翻转点并进行相应调整。它有点骇人听闻,但这里有一个简单的例子:

        TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
        Calendar cal = Calendar.getInstance(timeZone);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
        formatter.setTimeZone(timeZone);
        cal.set(Calendar.YEAR, 2015);
        cal.set(Calendar.MONTH, 10);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        boolean isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
        for (int i = 0; i < 25; i++) {
            cal.roll(Calendar.HOUR_OF_DAY, 1);
            if(isPreviousHour23){
                cal.roll(Calendar.HOUR_OF_DAY, -1);
            }
            isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
            System.out.println("Formatted  date: " + formatter.format(cal.getTime()));
        }
    

    给你这个输出:

    Formatted  date: 2015.11.01 22:24:13 EST
    Formatted  date: 2015.11.01 23:24:13 EST
    Formatted  date: 2015.11.01 00:24:13 EDT
    Formatted  date: 2015.11.01 01:24:13 EDT
    Formatted  date: 2015.11.01 01:24:13 EST
    Formatted  date: 2015.11.01 02:24:13 EST
    Formatted  date: 2015.11.01 03:24:13 EST
    Formatted  date: 2015.11.01 04:24:13 EST
    

    【讨论】:

    • 谢谢你的回答,但我需要 roll() - 不是为了增加天数
    • 您可能需要输入一些自定义逻辑来检查 EST 翻转然后...每当时间接近 00 时,EST 标志翻转并添加小时。因此,您需要检查前一小时是否为 23 和 EST 并手动设置小时(或回滚?)。
    • 这是我的第一个想法,但我希望找到更简单的方法。现在在我看来这是唯一的方法:) 谢谢!
    • 是的,不幸的是,roll 似乎不是一个非常可靠的功能。 :(
    猜你喜欢
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 2017-08-13
    相关资源
    最近更新 更多