为什么减去这两次(1927年)会得到一个奇怪的结果?

2022-08-31 01:22:07

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

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-ld31353

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

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

然后将是.ld4-ld31


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

答案 1

这是12月31日在上海的时区变化。

有关1927年在上海的详细信息,请参阅此页面。基本上在1927年底的午夜,时钟倒退了5分52秒。因此,“1927-12-31 23:54:08”实际上发生了两次,看起来Java正在将其解析为该本地日期/时间的较晚可能时刻 - 因此存在差异。

这只是时区中经常奇怪而美妙的世界中的又一集。

编辑:停止按压!历史记录更改...

如果使用TZDB的2013a版本重建,原始问题将不再表现出完全相同的行为。在 2013a 中,结果将为 358 秒,转换时间为 23:54:03 而不是 23:54:08。

我之所以注意到这一点,是因为我在野田时代以单元测试的形式收集了这样的问题......测试现在已经改变,但它只是表明 - 甚至历史数据都不是安全的。

编辑:历史又变了...

在 TZDB 2014f 中,更改时间已移至 1900-12-31,现在更改仅为 343 秒(因此,如果您明白我的意思,则和 之间的时间是 344 秒)。tt+1

编辑:为了回答一个关于1900年过渡的问题......看起来 Java 时区实现将所有时区都视为在 1900 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


答案 2

您遇到了本地时间不连续性

当地标准时间即将达到星期日时,1.1928年1月,00:00:00时钟向后0:05:52小时到31日星期六。12 月 1927,23:54:08 当地标准时间

这并不特别奇怪,并且由于政治或行政行为而切换或更改时区,几乎在任何地方都发生过这种情况。