【问题标题】:Java TimeZone head scratchingJava TimeZone 挠头
【发布时间】:2012-09-03 13:23:11
【问题描述】:

我想以夏令时证明格式保存一些用户时区。
我的目标是在代码执行时获得正确的 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?

【问题讨论】:

    标签: java timezone


    【解决方案1】:

    您遇到的一个问题是 182 * 86400000 溢出。如果你使用

    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);
    }
    

    打印

    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
    

    如果您查看 getTimeZone 的 javadoc 和源代码,您会看到

     * @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;
    }
    

    简而言之,EDT 不被识别,所以它变成了 GMT。

    【讨论】:

    • 那是你因为问一个愚蠢的问题而感到孤独的部分......谢谢:)
    • 这是一个很常见的问题(重新溢出)。这不是一个愚蠢的问题,请在谷歌中尝试how do i go,看看它对愚蠢问题的建议:D
    【解决方案2】:

    我怀疑这是问题所在:

    now + ( 182 * 86400000)
    

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

    now + ( 182 * 86400000L)
    

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

    不清楚究竟你要做什么,但我怀疑你真的应该只是保存时区 ID,例如“美国/纽约”。几乎所有其他事情都是自找麻烦。

    【讨论】:

      猜你喜欢
      • 2016-11-17
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 2014-11-28
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多