java - DateTimeFormatter 解析 - 时区名称和夏令时重叠时间

标签 java java-time

为了提高一些遗留代码的性能,我正在考虑用 java.time.format.DateTimeFormatter 替换 java.text.SimpleDateFormat。

执行的任务包括解析使用 java.util.Date.toString 序列化的日期/时间值。使用 SimpleDateFormat,可以将它们转回原始时间戳(忽略小数秒),但是在尝试使用 DateTimeFormatter 执行相同操作时我遇到了问题。

当使用其中任何一种进行格式化时,我的本地时区被指示为 CET 或 CEST,具体取决于夏令时是否对要格式化的时间有效。然而,在解析时,CET 和 CEST 似乎被 DateTimeFormatter 视为相同。

这会在夏令时结束时产生重叠问题。格式化时,02:00:00 被创建两次,每次间隔一小时,但使用 CEST 和 CET 时区名称 - 这很好。但在解析时,无法回收该差异。

这是一个例子:

long msecPerHour = 3600000L;
long cet_dst_2016 = 1477778400000L;
DateTimeFormatter formatter =
    DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
ZoneId timezone = ZoneId.of("Europe/Berlin");
for (int hours = 0; hours < 6; ++hours) {
    long time = cet_dst_2016 + msecPerHour * hours;
    String formatted = formatter.format(Instant.ofEpochMilli(time).atZone(timezone));
    long parsedTime = Instant.from(formatter.parse(formatted)).toEpochMilli();
    System.out.println(formatted + ", diff: " + (parsedTime - time));
}

结果

Sun Oct 30 00:00:00 CEST 2016, diff: 0
Sun Oct 30 01:00:00 CEST 2016, diff: 0
Sun Oct 30 02:00:00 CEST 2016, diff: 0
Sun Oct 30 02:00:00 CET 2016, diff: -3600000
Sun Oct 30 03:00:00 CET 2016, diff: 0
Sun Oct 30 04:00:00 CET 2016, diff: 0

它表明,尽管时区名称不同,但第二次出现的 02:00:00 被当作第一次出现。因此,结果实际上偏离了一个小时。

显然,格式化字符串具有所有可用信息,SimpleDateFormat 解析实际上尊重它。是否可以使用 DateTimeFormatter 和给定的模式来回格式化和解析?

最佳答案

对于特定情况是可能的:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("EEE MMM dd HH:mm:ss ")
    .appendText(OFFSET_SECONDS, ImmutableMap.of(2L * 60 * 60, "CEST", 1L * 60 * 60, "CET"))
    .appendPattern(" yyyy")
    .toFormatter(Locale.ENGLISH);

这会将确切的偏移量映射到预期的文本。当您需要处理多个时区时,这种做法会失败。

要正确完成这项工作需要 JDK change .

关于java - DateTimeFormatter 解析 - 时区名称和夏令时重叠时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43102957/

相关文章:

java代理将请求传递给上游应用程序

java - ZoneIds 在其他平台上的可用性

java - 如何避免时差为负时间?

java - 找不到符号类@load

java - 通过JDBC向PostgreSQL表中插入 "daterange"字段值

java - java.time.Clock.systemDefaultZone().getZone() 与 java.util.TimeZone.getDefault().toZoneId() 之间有什么区别?

Java:解析 ISO_DATE/ISO_OFFSET_DATE

java - 时间格式最终在生产中发生变化

java - 错误 - 从 java 代码运行 vbscript

java - Java 对象的 null 属性是否使用内存?