如果我运行下列程序,它分开两个日期线的参考时间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

当前回答

出口 LC_ALL=C TZ=UTC 设置系统时钟到 UTC 永远不会使用定位实施,除非绝对必要(即仅显示)

对于Java Community Process的成员,我建议:

做定位的方法,而不是默认,但要求用户明确要求定位. 使用 UTF-8/UTC 作为固定默认,而不是因为这只是今天的默认。

我指的是,来吧,全球静态变量不是一个反OO模式吗?没有别的东西是那些由某些基本的环境变量给予的突破性缺陷......。

其他回答

当增加时间时,您应该转换为UTC,然后添加或提取。

这样,你就可以通过任何时间或分钟发生两次。

如果你转换到 UTC,添加每秒,并转换到当地时间显示. 你会通过 11:54:08 下午 LMT - 11:59:59 下午 LMT 然后 11:54:08 下午 CST - 11:59:59 下午 CST.

出口 LC_ALL=C TZ=UTC 设置系统时钟到 UTC 永远不会使用定位实施,除非绝对必要(即仅显示)

对于Java Community Process的成员,我建议:

做定位的方法,而不是默认,但要求用户明确要求定位. 使用 UTF-8/UTC 作为固定默认,而不是因为这只是今天的默认。

我指的是,来吧,全球静态变量不是一个反OO模式吗?没有别的东西是那些由某些基本的环境变量给予的突破性缺陷......。

正如其他人所解释的那样,有时间停滞在那里. 在亚洲/上海,有2个可能的时间区差距为1927-12-31 23:54:08 但只有1个差距为1927-12-31 23:54:07. 因此,取决于使用的差距,有1秒差距或5分钟和53秒差距。

这种轻微的交换,而不是我们习惯的一个小时的日光节约(夏季时间),隐藏了这个问题一点。

在 Java 8 上使用新的 java.time 包,让您更清楚地看到这一点,并提供工具来处理它。

DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.append(DateTimeFormatter.ISO_LOCAL_DATE);
dtfb.appendLiteral(' ');
dtfb.append(DateTimeFormatter.ISO_LOCAL_TIME);
DateTimeFormatter dtf = dtfb.toFormatter();
ZoneId shanghai = ZoneId.of("Asia/Shanghai");

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

ZonedDateTime zdt3 = LocalDateTime.parse(str3, dtf).atZone(shanghai);
ZonedDateTime zdt4 = LocalDateTime.parse(str4, dtf).atZone(shanghai);

Duration durationAtEarlierOffset = Duration.between(zdt3.withEarlierOffsetAtOverlap(), zdt4.withEarlierOffsetAtOverlap());

Duration durationAtLaterOffset = Duration.between(zdt3.withLaterOffsetAtOverlap(), zdt4.withLaterOffsetAtOverlap());

此外,这两个外套是相同的:

// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();

但这两种是不同的:

// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();

// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();

// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);

// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);

您可以检查过渡是否是一个过渡,如果有超过一个有效的折扣为该日期/时间或一个差距,如果该日期/时间不适用于该区域ID - 使用 isOverlap() 和 isGap() 方法在 zot4 。

这个奇怪的道德是:

使用 UTC 的日期和时间在任何可能的地方. 如果您无法在 UTC 中显示日期或时间,请始终指示时间区. 如果您无法在 UTC 中要求输入日期/时间,请明确指示时间区。

我很抱歉说,但时间间断已经移动了一点。

JDK 6 兩年前,並在 JDK 7 最近更新 25.

学习的教训:以任何代价避免非UTC时间,除非可能显示。