Pet*_*ser 6 java iso date timezone-offset java-time
对于 REST Web 服务,我需要返回带有时区的日期(无时间)。
ZonedDate显然, Java 中没有 a 这样的东西(只有LocalDate和ZonedDateTime),所以我使用它ZonedDateTime作为后备。
将这些日期转换为 JSON 时,我使用DateTimeFormatter.ISO_OFFSET_DATE格式化日期,效果非常好:
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE;
ZonedDateTime dateTime = ZonedDateTime.now();
String formatted = dateTime.format(formatter);
Run Code Online (Sandbox Code Playgroud)
2018-04-19+02:00
然而,尝试解析这样的日期......
ZonedDateTime parsed = ZonedDateTime.parse(formatted, formatter);
Run Code Online (Sandbox Code Playgroud)
...导致异常:
java.time.format.DateTimeParseException:无法解析文本“2018-04-19+02:00”:无法从 TemporalAccessor 获取 ZonedDateTime:{OffsetSeconds=7200},ISO 解析为 java 类型的 2018-04-19。时间.格式.解析
我也尝试过ISO_DATE并遇到了同样的问题。
我如何解析这样的分区日期?
或者是否有任何其他类型(在 Java Time API 内)我应该用于分区日期?
小智 6
问题是ZonedDateTime需要构建所有日期和时间字段(年、月、日、小时、分钟、秒、纳秒),但格式化程序ISO_OFFSET_DATE生成一个没有时间部分的字符串。
当解析它时,没有与时间相关的字段(小时、分钟、秒),并且您得到一个DateTimeParseException.
解析它的一种替代方法是使用 aDateTimeFormatterBuilder并为时间字段定义默认值。正如您atStartOfDay在答案中所使用的那样,我假设您想要午夜,因此您可以执行以下操作:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date and offset
.append(DateTimeFormatter.ISO_OFFSET_DATE)
// default values for hour and minute
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.toFormatter();
ZonedDateTime parsed = ZonedDateTime.parse("2018-04-19+02:00", fmt); // 2018-04-19T00:00+02:00
Run Code Online (Sandbox Code Playgroud)
您的解决方案也可以正常工作,但唯一的问题是您解析输入两次(每次调用formatter.parse都会再次解析输入)。更好的替代方法是使用parse没有临时查询的方法(仅解析一次),然后使用解析的对象来获取所需的信息。
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE;
// parse input
TemporalAccessor parsed = formatter.parse("2018-04-19+02:00");
// get data from the parsed object
LocalDate date = LocalDate.from(parsed);
ZoneId zone = ZoneId.from(parsed);
ZonedDateTime restored = date.atStartOfDay(zone); // 2018-04-19T00:00+02:00
Run Code Online (Sandbox Code Playgroud)
使用此解决方案,输入仅被解析一次。
我找到了解决方案(使用TemporalQueries):
分别解析日期和区域,并使用该信息恢复分区日期:
LocalDate date = formatter.parse(formatted, TemporalQueries.localDate());
ZoneId zone = formatter.parse(formatted, TemporalQueries.zone());
ZonedDateTime restored = date.atStartOfDay(zone);
Run Code Online (Sandbox Code Playgroud)