问题

如果我运行下面的程序,它解析两个日期字符串引用的时间相隔一秒,并比较它们:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

输出为:

353

为什么 ld4-ld3 不是 1 (我希望从时间的一秒差异),但 353 ?

如果我将日期更改为1秒后的时间:

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

那么 ld4-ld3 将会是 1 .


Java版本:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)

Timezone(`TimeZone.getDefault()`):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN


解决方法

这是12月31日在上海的时区变更.

有关1927年的详情,请参阅此网页上海.基本上在1927年年底的午夜,时钟回去5分52秒.所以"1927-12-31 23:54:08"实际上发生了两次,看起来Java正在解析它作为本地日期/时间的可能的时间 - 因此差异.

只是另一集在时常奇怪和美好的时区世界.

编辑:停止新闻!历史记录更改...

如果使用 TZDB .在2013a,结果将是358秒,转换时间为23:54:03而不是23:54:08.

我只注意到这个,因为我在Noda时间收集这样的问题,形式是单元测试 ...测试现在已经更改,但它只是显示 - 甚至没有历史数据是安全的.

编辑:历史记录已再次更改...

在TZDB 2014f中,更改时间已移至1900-12-31,现在只有343秒的更改(因此 t t + 1 < / code>是344秒,如果你看到我的意思).

编辑:要回答 Ken Kin的问题围绕1900年的转换...看起来Java时区实现将所有时区视为只是在其标准时间对于UTC UTC开始之前的任何时刻:

import java.util.TimeZone;

public class Test {
    public static void main(String[] args) throws Exception {
        long startOf1900Utc = -2208988800000L;
        for (String id : TimeZone.getAvailableIDs()) {
            TimeZone zone = TimeZone.getTimeZone(id);
            if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
                System.out.println(id);
            }
        }
    }
}

上面的代码在我的Windows机器上没有产生输出.因此,任何在1900年开始时具有除了标准偏移之外的任何偏移的时区将将其计算为过渡. TZDB本身有一些数据早于这些,并不依赖于任何想法的"固定"标准时间(这是 getRawOffset 假设是一个有效的概念),所以其他库需要' t引入这种人为过渡.




相关问题推荐