为什么减去两次(在 1927 年)会得到一个奇怪的结果?
技术问答
211 人阅读
|
0 人回复
|
2023-09-11
|
如果我操作以下程序,它将分析相隔 1 秒的两个日期字符串,并比较它们:6 n( f$ T# `( E
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);}- i( A: j. q- y9 P8 Y
输出是:! Y; q1 x& |' `# z/ u& x
3534 R+ u6 |* V& Z. g; p4 t1 E% a I7 c
为什么是ld4-ld3.不是1(就像我期待的时差一秒),而是353?
% u$ o1 i5 X& g假如我把日期改为 1 秒后的时间:6 H8 S* P# L/ T# C" w, N0 ^
String str3 = "1927-12-31 23:54:08"; String str4 = "1927-12-31 23:54:09";
8 \0 `5 f9 Q4 j* d9 g/ D 然后ld4-ld3将是1。! c, ?7 r# z v) K" d/ Q1 v" i
java版:
9 W$ Z0 Y% Z/ o& e( c8 Sjava 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_CN5 x- r! r% \( B9 N
# c' W2 M% z4 s. O! S3 F2 Z
解决方案: . [4 N# ~& i" w% V
12 月 31 日是上海时区的变化。
, k$ n$ ^- p. J+ u- s/ G' p g请参阅本页1927年上海的详细信息。基本上在 1927 年底的午夜,时钟倒退了 5分 52 秒。因此,1927-12-31 23:54:08实际上发生了两次,看起来 Java 将其分析为本地日期/时间较晚可能时刻-因此存在差异。
5 C& h; Q' D& D5 w只是时区奇特而美好世界的又一集。2 ~4 K1 [2 U4 w2 T3 A6 A2 w, k
编辑:停止按!历史变…5 n" K5 W" f. D+ H
如果使用 TZDB 的2013a在版本重建中,原始问题将不再表现出完全相同的行为。 2013a 结果为 358 秒,转换时间为 23:54:03 ,而不是 23:54:08。
, c2 u5 M9 j I( N: W我只是注意到了这一点,因为我在 Noda Time 以单元测试的形式收集此类问题......测试现在已经改变了,但它只显示 - 甚至历史数据也不安全。
' b1 ?* M& }- Q0 x ]编辑:历史又变了......
/ D U* |/ T0 V2 [3 o0 y& W; ]# L在TZDB 2014F,时间变化已经转移到1900年12月31日,现在是一个简单的343秒变化(这样的时间t和t 1有344秒,如果你明白我的意思)。
6 k0 W- s* n+ T' e1 l* S编辑:要回答 1900 年过渡的问题......看起来 Java 实现时区将所有时区视为在 1900 UTC 开始前的任何时候都是标准时间:. w/ k% i+ M; r5 [! ^
[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因此,其他图书馆不需要引入这种人工转换。 |
|
|
|
|
|