在Java时区东欧夏令时(EEST)中添加天数

3

我写了一个Java应用程序,开始日期是特定年份的1月1日00:00。然后我增加了355天并一路打印出结果。我试图理解夏令时周围时区是如何工作的,如果添加1天是否会在进入夏令时时将时间从午夜转移到凌晨1点。我的代码如下:

TimeZone tz = TimeZone.getDefault();
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss z");
sdf.setTimeZone(tz);
Calendar cal = Calendar.getInstance(tz);
cal.set(2008, 0, 1, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
for ( int i = 0; i < 355; i++ ) {
    System.out.println(sdf.format(cal.getTime()));
    cal.add(Calendar.DAY_OF_MONTH, 1);
}

当在我的默认时区(美国东部)运行时,输出看起来与我预期的一样:
01/01/2008 00:00:00 EST
01/02/2008 00:00:00 EST
01/03/2008 00:00:00 EST
01/04/2008 00:00:00 EST
...

当我跨入夏令时时,会有

03/10/2008 00:00:00 EDT
03/11/2008 00:00:00 EDT
03/12/2008 00:00:00 EDT

当我使用一个遵循东欧夏令时的时区(在这种情况下,我选择了非洲/开罗时区),我会得到以下输出:
01/01/2008 00:00:00 EET
01/02/2008 00:00:00 EET
01/03/2008 00:00:00 EET
01/04/2008 00:00:00 EET
01/05/2008 00:00:00 EET

但是当我进入东欧夏令时,我收到以下信息:
04/25/2008 01:00:00 EEST
04/26/2008 01:00:00 EEST
04/27/2008 01:00:00 EEST

神奇的是,EEST结束后,我仍然会得到

08/29/2008 01:00:00 EET
08/30/2008 01:00:00 EET

我对这些时区为何表现不同感到困惑,不确定是非洲/开罗时区的错误还是我对时区工作原理的误解......如果您能提供任何见解,将不胜感激。

你正在使用哪个Java版本?你是否已经更新了最新的JRE时区数据库? - kosa
我正在使用Java 6更新29版...现在正在更新到30版... - Jeff Storey
1个回答

3

开罗时区在午夜时刻转入夏令时-因此2008年4月25日午夜之间的一小时被跳过了...挂钟变成了:

04/24/2008 23:59:58
04/24/2008 23:59:59
04/25/2008 01:00:00
04/25/2008 01:00:01

尝试从美国东部时间2点开始,每天添加一天,你会看到同样的事情-在某个时刻它将变为03:00。

不清楚你确切想要实现什么-我倾向于认为最好是将“一定数目的经验毫秒数”添加到特定时区的日期/时间中,或将“一定数目的逻辑毫秒数”添加到本地日期/时间中,它不考虑时区。当你从本地时间转换到特定区域的时间时,需要考虑可能出现的歧义(一个本地时间发生两次)或跳过(一个本地时间根本不出现)的可能性。

另外,去年萨摩亚跳过了整整12月30日,因为它将时区从-14更改为+10...

编辑:哦,并且我的标准建议适用:放弃java.util.Calendar / Date,并使用Joda Time


Jon,谢谢。我相信这是问题的一部分。但是当离开EEST时,我希望看到类似的行为...不一致似乎是不正确的。但是为了澄清我想做什么,我基本上只是想创建一组从午夜到午夜的时间段。我理解在我们跨越节约时间的那些日子里,时间段可能是23或25个小时(或者甚至那天午夜可能不存在)。 - Jeff Storey
@JeffStorey:不,因为当离开东欧夏令时(EEST)时,当地时间01:00会出现两次。基本上一旦你离开午夜,你就再也不会遇到当地时间不存在的情况了。 - Jon Skeet
对于您在JODA时间上的编辑,我通常会这样做,但我正在与使用Java Calendar/Date的现有API集成。我知道我可以在两者之间进行转换,所以如果需要,我会这样做。 - Jeff Storey
@JeffStorey:我不确定你在这里所说的“DST”的意思,但是添加“一天”的尝试是为了到达“下一个日期的相同(本地)时间”......但是当该本地时间不存在时,就会出现问题。这并不是说添加一天有不同的含义-而是你恰好避免了你的美国样本中的问题时间。正如我所说的,在美国从凌晨2点开始尝试,你会看到同样的情况... - Jon Skeet
我现在明白了,这很有道理。我刚试了一下,发现同样的情况出现了(时间从0200变成了0100)。所以我基本上是想要打印始终从0000开始的等间隔时间。当那个时间不存在时,它是0100,但是我希望它在第二天再次从0000开始--不确定如何以一般方式实现这一点。 - Jeff Storey
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接