Java Calendar.roll-over DST begin/end的值不正确

Java Calendar.roll-over DST begin/end的值不正确,java,calendar,timezone,Java,Calendar,Timezone,当您尝试滚动DST开始或结束的日期时,会出现此问题。例如,我们可以将“美国/纽约”时区设置为2015年11月1日日历(EDT更改为EST的日期),并尝试滚动: TimeZone timeZone = TimeZone.getTimeZone("America/New_York"); Calendar cal = Calendar.getInstance(timeZone); SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd

当您尝试滚动DST开始或结束的日期时,会出现此问题。例如,我们可以将“美国/纽约”时区设置为2015年11月1日日历(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()));
}
TimeZone TimeZone=TimeZone.getTimeZone(“美国/纽约”);
Calendar cal=Calendar.getInstance(时区);
SimpleDataFormat格式化程序=新的SimpleDataFormat(“yyyy.MM.dd HH:MM:ss z”);
格式化程序。设置时区(时区);
校准集(日历年,2015年);
校准设置(日历月,10);
校准设置(日历日/月/日,1);
对于(int i=0;i<24;i++)
{
校准辊(日历小时/天,1);
System.out.println(“格式化日期:+formatter.format(cal.getTime()));
}
结果是:
。。。
格式日期:2015.11.01 22:08:32东部标准时间
格式化日期:美国东部时间2015.11.01 23:08:32
格式化日期:美国东部夏令时2015.11.01:08:32
格式日期:2015.11.01 01:08:32东部标准时间
格式日期:2015.11.01 02:08:32东部标准时间

看看
roll
javadoc

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

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


由于必须使用
滚动
,请添加一些自定义逻辑来确定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()));
    }

谢谢你的回答,但我需要确切的滚动()-不要增加天数,你可能需要加入一些自定义逻辑来检查EST滚动,然后。。。每当时间接近00时,EST标志将翻转并添加小时。因此,您需要检查前一个小时是否为23和EST,并手动设置小时(或回滚一个小时?),这是我的第一个想法,但我希望找到更简单的方法。现在在我看来,这是唯一的办法:)谢谢!是的,不幸的是,
roll
似乎不是一个非常可靠的函数:(
    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