UTC
始终使用UTC进行数据交换和这种读数记录。始终,始终使用UTC。将UTC视为一个真实时间和其他时区与UTC的偏差。
顺便说一句,Daylight Saving Time (DST)是不是唯一的问题是担心区划日期时间值。其他异常发生在各个时区,导致wall-clock time向前或向后移动。解决方案很简单:避免使用所有时区 - 使用UTC。
Instant
的Instant
类捕获UTC时间线与纳秒的分辨率上一会儿。这应该是你去上课的日期时间工作。
Instant instant = Instant.now();
字符串
用于记录,生成标准ISO 8601格式的字符串。坚持采用经过验证的ISO 8601格式,而不是发明自己的产品。
包括Instant
的java.time类在解析/生成字符串时默认使用ISO 8601格式。所以不需要指定格式化模式。
String output = instant.toString();
2016-11-02T21:10:05.321Z
Instant instant = Instant.parse("2016-11-02T21:10:05.321Z");
而且始终在您的日期世纪20
。忽略只会为错误解释中的错误创造很多机会。存储和内存真的很便宜,我们可以负担两个额外的数字。
时区指针
始终包括时区或偏移从-UTC指标与序列化日期时间值。
在上面看到的Instant::toString
结果中,Z
代表Zulu
,表示UTC。
解析字符串
下面是代码来解析您的日期时间字符串。我们首先解析为LocalDateTime
,没有任何时区或偏移量,因为您的输入缺少任何时区或偏移量的指示符。然后我们分配一个时区来获得ZonedDateTime
,以了解它如何处理DST切换的时刻。
我认为问题所在时区使用凌晨2点的DST回退割接。作为这样的例子,我使用America/Montreal
。
List<String> inputs = new ArrayList<>(2);
inputs.add("141102 0115"); // 1 AM
inputs.add("141102 0215"); // 2 AM
for(String input : inputs) {
DateTimeFormatter f = DateTimeFormatter.ofPattern("uuMMdd HHmm");
LocalDateTime ldt = LocalDateTime.parse(input , f);
// At 2 AM in this zone, the clock falls back one hour for DST cutover. The 1 AM hour repeats.
ZoneId z = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ldt.atZone(z);
System.out.println("input: " + input);
System.out.println("ldt: " + ldt);
System.out.println("zdt: " + zdt);
System.out.println("instant: " + zdt.toInstant());
System.out.println("");
}
输入:141102 0115
LDT:2014-11-02T01:15
ZDT:2014-11-02T01:15-04:00 [美国/蒙特利尔]
瞬间:2014-11-02T05:15:00Z
......还有......
输入:141102 0215
LDT:2014-11-02T02:15
ZDT:2014-11-02T02:15-05:00 [美国/蒙特利尔]
瞬间: 2014-11-02T07:15:00Z
您可以see this code live in IdeOne.com。请注意UTC值的两小时差异(Z
)。
我们看到的行为被记录在案。
在大多数情况下,本地日期时间只有一个有效偏移量。在时钟重新设置的情况下,有两个有效的偏移量。此方法使用通常对应于“夏季”的较早的偏移量。
上午1点15分含糊不清,可能是第一或第二次出现java。时间与第一次一样。
你可以玩猜谜游戏来尝试调整这些糟糕设计的字符串。如果您确定在每个时钟小时内至少有一个样本,则可以跟踪以前的样本并查看正在处理的样本是否比以前的时钟早。如果是这样,你可以认为这是一个DST后退切换,并添加一小时plusHours(1)
。
if(processingZdt.toLocalDateTime().isBefore(previousZdt.toLocalDateTime()) {
processingZdt.plusHours(1) ; // A hack; I am *not* recommending this.
…
但是,这是一个解决方案的冒险攻击。我不确定这项工作,因为我没有想到它通过。如果绝望,也许你可以让它工作。
明智的做法是预防:使用UTC。
所以你真正想要做的是将日期转换为一个文件名,使用的时区在夏天不会改变它的偏移量,对吧? –
它不是文件名,而是文件中有'timestamp'的一行。我想在dst的一个小时内转换该时间戳,以便我没有缺口或重复的条目。 – DHines
好的,但不会只使用日期格式没有夏时制的时区达到那个目的?或者我错过了什么?标准做法是在日志文件中使用UTC作为时间戳,但大概您更希望在冬天您的时区与您的时区保持一致。 –