1

我想以夏令时证明格式保存一些用户时区。
我的目标是在代码执行时获得正确的 GMT 偏移量。
为了找出我最好的选择,我写了以下内容:

ArrayList<String> list = new ArrayList<String>();
list.add( "EST");
list.add( "EDT");
list.add( "America/New_York");
long now = System.currentTimeMillis();
for( String tzID: list) {
    TimeZone tz = TimeZone.getTimeZone( tzID);
    System.out.println( tzID + " now=" + tz.getOffset( now) / 3600000 + " / +182=" + tz.getOffset( now + ( 182 * 86400000)) / 3600000);
}

简而言之,现在给我偏移量,在 182 天内
执行 9 月 3 日,输出是

EST now=-5 / +182=-5
EDT now=0 / +182=0
America/New_York now=-4 / +182=-4

出于以下几个原因,这是出乎意料的
1) 为什么 America/New_York 不给 -4/-5 ?,它不应该对日期敏感吗?
2) 为什么 EDT == UTC?

4

2 回答 2

3

One problem you have is that 182 * 86400000 overflows. If you use

long now = System.currentTimeMillis();
for( String tzID: "EST,EDT,America/New_York".split(",")) {
    TimeZone tz = TimeZone.getTimeZone( tzID);
    System.out.println( tz.getDisplayName() + " now=" + tz.getOffset( now) / 36e5 
                     + " / +182=" + tz.getOffset( now + 182 * 86400000L) / 36e5);
}

prints

Eastern Standard Time now=-5.0 / +182=-5.0
Greenwich Mean Time now=0.0 / +182=0.0
Eastern Standard Time now=-4.0 / +182=-5.0

If you look at the javadoc and source for getTimeZone you can see

 * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
 * cannot be understood.

public static synchronized TimeZone getTimeZone(String ID) {
return getTimeZone(ID, true);
}

private static TimeZone getTimeZone(String ID, boolean fallback) {
TimeZone tz = ZoneInfo.getTimeZone(ID);
if (tz == null) {
    tz = parseCustomTimeZone(ID);
    if (tz == null && fallback) {
    tz = new ZoneInfo(GMT_ID, 0);
    }
}
return tz;
}

In short, EDT is not recognised so it becomes GMT.

于 2012-09-03T13:27:21.290 回答
2

我怀疑这是问题所在:

now + ( 182 * 86400000)

带括号的算术表达式溢出 32 位。你可能想要:

now + ( 182 * 86400000L)

然而,这仍然假设任何夏令时将应用大约六个月,这在现实世界中肯定不是这种情况。例如,查看Sao Paolo 时区,它会在 10 月和 2 月切换 - 因此,如果您在 9 月运行代码,您最终会看到 -3 / -3。即使对于 DST 大约每六个月打开/关闭一次的时区,您也很可能会发现每年连续 182 天没有切换(几乎按照定义,因为这略少于半年)。

目前尚不清楚要做什么,但我怀疑您真的应该只保存时区 ID,例如“America/New_York”。几乎所有其他事情都是自找麻烦。

于 2012-09-03T13:25:01.250 回答