为了提高某些遗留代码的性能,我正在考虑用 java.time.format.DateTimeFormatter 替换 java.text.SimpleDateFormat。
执行的任务之一是解析使用 java.util.Date.toString 序列化的日期/时间值。使用 SimpleDateFormat,可以将它们转回原始时间戳(忽略小数秒),但是在尝试使用 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));
}
Run Code Online (Sandbox Code Playgroud)
这导致
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
Run Code Online (Sandbox Code Playgroud)
它表明,尽管时区名称不同,但第二次出现的 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);
Run Code Online (Sandbox Code Playgroud)
这将精确的偏移量映射到预期文本。当您需要处理多个时区时,这种方法就会失败。
要正确完成这项工作,需要更改 JDK。
| 归档时间: |
|
| 查看次数: |
1565 次 |
| 最近记录: |