java - 为什么减去这两次(在 1927 年)会产生奇怪的结果?

标签 java date timezone

如果我运行以下程序,它会解析两个引用时间相隔 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-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 日上海时区变化。

this page 1927年在上海的详细资料。基本上在 1927 年底的午夜,时钟倒退了 5 分 52 秒。所以“1927-12-31 23:54:08”实际上发生了两次,看起来 Java 将其解析为该本地日期/时间的 later 可能瞬间 - 因此存在差异。 p>

这只是时区经常奇怪而美妙的世界中的另一个插曲。

编辑:停止按下!历史变迁……

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

我之所以注意到这一点,是因为我正在野田时间收集这样的问题,形式为 unit tests ... 现在测试已更改,但它只是表明 - 甚至历史数据也不安全。

编辑:历史再次改变...

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

编辑:要回答有关 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 假设是一个有效的概念),因此其他库不需要' t 引入这种人为的过渡。

关于java - 为什么减去这两次(在 1927 年)会产生奇怪的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6841333/

相关文章:

objective-c - 使用带时区的 NSDateFormatter 将 NSDate 转换为 NSString,无需 GMT 时间修改器

asp.net - 从 SQL 2005 Server 访问 TimeZoneInfo

php - 修复在 Linux 上运行的 PHP 中的时间格式警告

java - RecyclerView 在 List 上显示删除的数据

java - 为什么 getFile 的这个实例可以与 SVNKit 一起使用?

javascript - 在javascript中计算两个给定时间的时间差(以毫秒为单位),格式为 "DD/MM/YYYY HH:mm:ss:ms"

javascript - 如果输入日期少于 4 个月,则禁用按钮

sql-server - 区域日期格式和数据库日期格式的不同日期格式的 SQL Server 错误

java - 更改小部件中 TextView 的字体?

Java泛型类型删除字节码