Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c4ef2b4

Browse filesBrowse files
committed
Why is subtracting these two times (in 1927) giving a strange result?
1 parent a4adac5 commit c4ef2b4
Copy full SHA for c4ef2b4

File tree

Expand file treeCollapse file tree

1 file changed

+80
-0
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+80
-0
lines changed
+80Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
## 为什么相减这两个时间(1927年)会得到奇怪的结果?
2+
3+
### 问题
4+
如果运行下面的代码,我想要做的是解析两个相差1秒的日期字符串:
5+
```java
6+
public static void main(String[] args) throws ParseException {
7+
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
8+
String str3 = "1927-12-31 23:54:07";
9+
String str4 = "1927-12-31 23:54:08";
10+
Date sDt3 = sf.parse(str3);
11+
Date sDt4 = sf.parse(str4);
12+
long ld3 = sDt3.getTime() /1000;
13+
long ld4 = sDt4.getTime() /1000;
14+
System.out.println(ld4-ld3);
15+
}
16+
```
17+
其结果是
18+
```
19+
353
20+
```
21+
为什么`ld4-ld3` 结果不是`1`(因为我期望得到1秒的时间差)而是`353`
22+
23+
如果我把两个日期都换成1秒后:
24+
```java
25+
String str3 = "1927-12-31 23:54:08";
26+
String str4 = "1927-12-31 23:54:09";
27+
```
28+
这样`ld4-ld3`就为`1`
29+
30+
---
31+
java 版本
32+
```
33+
java version "1.6.0_22"
34+
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
35+
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)
36+
```
37+
时区(`TimeZone.getDefault()`):
38+
```
39+
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
40+
offset=28800000,dstSavings=0,
41+
useDaylight=false,
42+
transitions=19,
43+
lastRule=null]
44+
45+
Locale(Locale.getDefault()): zh_CN
46+
```
47+
## 回答
48+
这是12月31号上海时区切换的错误。
49+
50+
[这个页面](http://www.timeanddate.com/time/change/china/shanghai?year=1927)上有关于上海1927的详细说明。因为1927年末尾的午夜,时间回滚了5分52秒,所以"1927-12-31 23:54:08" 实际上发生了两次,并且很明显java解析立即得到了可能的后面一个,而忽略了其差别。
51+
52+
这在经常弄混且丰富的世界时区中还是一个插曲。
53+
54+
如果重新编译[TZDB](https://github.com/nodatime/nodatime/blob/master/src/NodaTime.Demo/StackOverflowExamples.cs#L68)的2013a版本,之前的问题就不再能解释类型行为。在2013a 的版本中,结果将是358秒,切换时间由23:54:03 变为23:54:08。
55+
56+
我能注意到这个都是因为我在[unit tests](https://github.com/nodatime/nodatime/blob/master/src/NodaTime.Demo/StackOverflowExamples.cs#L68)收集像Noda Time 这样的问题
57+
58+
这个测试现在已经被更新,但是也表明没有历史数据是安全的。
59+
60+
在TZDB 2014f中, 这个时间切换移动到了1900-12-31,并且也被修改成唯一的343秒变化(如果你知道我在说啥的话,`t``t+1` 之间是343 秒)。
61+
62+
**更新** 为了回答[ Ken Kin's question](http://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result/6841479#comment22684267_6841479)的问题,看起来像是,对于任何在1900 UTC 之前的时间,java 在他们的标准时间中进行了简单的时区实现。
63+
```java
64+
import java.util.TimeZone;
65+
66+
public class Test {
67+
public static void main(String[] args) throws Exception {
68+
long startOf1900Utc = -2208988800000L;
69+
for (String id : TimeZone.getAvailableIDs()) {
70+
TimeZone zone = TimeZone.getTimeZone(id);
71+
if (zone.getRawOffset() != zone.getOffset(startOf1900Utc - 1)) {
72+
System.out.println(id);
73+
}
74+
}
75+
}
76+
}
77+
```
78+
上面的代码在我的windows 机器上没有任何输出,所以对于任何相对标准时间在1900年前且有偏移的时间,都会有时间过渡。TZDB 自己有数据回退到更早之前,并且不依赖任何修正过的标准时间(就是`getRawOffset`假设的有效的概念),所以其他库不再需要介绍这个切换。
79+
80+
stackoverflow[链接](http://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.