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

Java DateTimeFormatter解析-时区名称和夏令时重叠时间,java,java-time,Java,Java Time,为了提高一些遗留代码的性能,我正在考虑用java.time.format.DateTimeFormatter替换java.text.simpleDataFormat 执行的任务包括解析使用java.util.date.toString序列化的日期/时间值。使用SimpleDataFormat,可以将它们转换回原始时间戳(忽略小数秒),但是,在尝试使用DateTimeFormatter执行相同操作时,我会遇到问题 使用其中一种设置格式时,我的本地时区显示为CET或CEST,具体取决于要设置格式的时

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

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

使用其中一种设置格式时,我的本地时区显示为CET或CEST,具体取决于要设置格式的时间是否为夏令时。然而,似乎在解析时,DateTimeFormatter对CET和CEST的处理是相同的

这会在夏令时结束时产生重叠问题。格式化时,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));
}
它表明,第二次出现02:00:00,尽管时区名称不同,但被视为与第一次相同。因此,结果有效地缩短了一个小时


显然,格式化字符串具有所有可用的信息,SimpleDataFormat解析事实上支持它。是否可以使用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问题。事实上,我还必须支持其他时区(例如PDT/PST),因此我将坚持使用SimpleDataFormat解析包含
z
说明符的模式。
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);