回答

收藏

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

技术问答 技术问答 304 人阅读 | 0 人回复 | 2023-09-11

如果我操作以下程序,它将分析相隔 1 秒的两个日期字符串,并比较它们:. c# o1 o: M. p' \# R8 _$ N
    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()  long ld4 = sDt4.getTime() /1000;   System.out.println(ld4-ld3);}& n0 l* I6 h% @1 Z
输出是:
1 T1 B- a5 }& \* y" k
    3538 z; J  G4 l8 x. y% T  s- w. F7 z
为什么是ld4-ld3.不是1(就像我期待的时差一秒),而是353?/ A8 m9 Q5 C. L# a: N
假如我把日期改为 1 秒后的时间:6 v7 l6 e+ Q* Q, S% E% \: X! I) [
    String str3 = "1927-12-31 23:54:08";  String str4 = "1927-12-31 23:54:09";  
    - ^. ?9 {( a7 n# w- J/ `3 W/ @0 T( h
然后ld4-ld3将是1。( W; F+ w" U% Y7 Y* L% G
java版:
# X$ ?3 r! O# h8 @( I: n; y
    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
    8 B( G: U" U- h8 c% q, [
               ) K  b2 g' }: N' J' @6 u; I1 U3 s
    解决方案:                                                               
" @# z# O* v$ j2 w" q8 I                                                                12 月 31 日是上海时区的变化。6 Y* J  {# G7 l  y; f. m
请参阅本页1927年上海的详细信息。基本上在 1927 年底的午夜,时钟倒退了 5分 52 秒。因此,1927-12-31 23:54:08实际上发生了两次,看起来 Java  将其分析为本地日期/时间较晚可能时刻-因此存在差异。/ n. |" Z: R6 L# A& J( Y
只是时区奇特而美好世界的又一集。) `" W6 [2 m( F6 J' o0 q
编辑:停止按!历史变…
# @  [, x" X# k; |如果使用 TZDB 的2013a在版本重建中,原始问题将不再表现出完全相同的行为。 2013a 结果为 358 秒,转换时间为 23:54:03 ,而不是 23:54:08。0 C. \; z/ g$ p/ b
我只是注意到了这一点,因为我在 Noda Time 以单元测试的形式收集此类问题......测试现在已经改变了,但它只显示 - 甚至历史数据也不安全。' {: f6 }6 r3 C, w
编辑:历史又变了......
( v1 a# n/ t9 n1 @' t在TZDB 2014F,时间变化已经转移到1900年12月31日,现在是一个简单的343秒变化(这样的时间t和t 1有344秒,如果你明白我的意思)。
) m& }( W+ _8 P1 G8 p5 B/ S编辑:要回答 1900 年过渡的问题......看起来 Java 实现时区将所有时区视为在 1900 UTC 开始前的任何时候都是标准时间:0 ^% i7 X0 m$ y& m6 Z
[code]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);            code]上面的代码在我的 Windows 机器上没有输出。因此,除标准偏移外, 1900 年初任何偏移区域都被视为过渡。TZDB 有一些比这更早的数据,不依赖任何固定标准时间的想法(这是getRawOffset因此,其他图书馆不需要引入这种人工转换。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则