Java:解析ISO_DATE / ISO_OFFSET_DATE [英] Java: parse ISO_DATE / ISO_OFFSET_DATE
问题描述
对于REST Web服务,我需要返回带有时区的日期(无时间)。
For a REST web service, I need to return dates (no time) with a time zone.
显然没有这样的日期在Java中是 ZonedDate
的东西(仅 LocalDate
和 ZonedDateTime
),因此我使用 ZonedDateTime
作为后备。
Apparently there is no such thing as a ZonedDate
in Java (only LocalDate
and ZonedDateTime
), so I'm using ZonedDateTime
as a fallback.
将这些日期转换为JSON时,我使用 DateTimeFormatter.ISO_OFFSET_DATE
格式化日期,确实很好:
When converting those dates to JSON, I use DateTimeFormatter.ISO_OFFSET_DATE
to format the date, which works really well:
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE;
ZonedDateTime dateTime = ZonedDateTime.now();
String formatted = dateTime.format(formatter);
2018-04-19 + 02:00
2018-04-19+02:00
但是,尝试用...解析这样的日期。
However, attempting to parse back such a date with...
ZonedDateTime parsed = ZonedDateTime.parse(formatted, formatter);
...导致异常:
java.time.format.DateTimeParseException:无法解析文本'2018-04-19 + 02:00':无法从TemporalAccessor获取ZonedDateTime:{OffsetSeconds = 7200},ISO解析为类型为java.time.format.Parsed的2018-04-19
java.time.format.DateTimeParseException: Text '2018-04-19+02:00' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {OffsetSeconds=7200},ISO resolved to 2018-04-19 of type java.time.format.Parsed
我也尝试过 ISO_DATE
并遇到了相同的问题。
I also tried ISO_DATE
and ran into the same problem.
我如何解析这样的分区日期?
还是我应该将其他任何类型(在Java Time API中使用)用于分区日期?
How can I parse such a zoned date back?
Or is there any other type (within the Java Time API) I'm supposed to use for zoned dates?
推荐答案
问题是 ZonedDateTime
需要构建所有日期和时间字段(年,月,日,时,分,秒,纳秒),但是格式化程序 ISO_OFFSET_DATE
会生成不带时间部分的字符串。
The problem is that ZonedDateTime
needs all the date and time fields to be built (year, month, day, hour, minute, second, nanosecond), but the formatter ISO_OFFSET_DATE
produces a string without the time part.
解析时,与时间无关字段(小时,分钟,秒),您会得到一个 DateTimeParseException
。
When parsing it back, there are no time-related fields (hours, minutes, seconds) and you get a DateTimeParseException
.
一种解析方法是使用 DateTimeFormatterBuilder
并定义时间字段的默认值。当您在回答中使用 atStartOfDay
时,我假设您想午夜,所以您可以执行以下操作:
One alternative to parse it is to use a DateTimeFormatterBuilder
and define default values for the time fields. As you used atStartOfDay
in your answer, I'm assuming you want midnight, so you can do the following:
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
您的解决方案也可以很好地工作,但是唯一的问题是您要解析输入两次 >(每次调用 formatter.parse
都会再次解析输入)。更好的选择是使用 parse
方法而不进行时间查询(仅分析一次),然后使用已分析的对象来获取所需的信息。
Your solution also works fine, but the only problem is that you're parsing the input twice (each call to formatter.parse
will parse the input again). A better alternative is to use the parse
method without a temporal query (parse only once), and then use the parsed object to get the information you need.
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
使用此解决方案,将解析输入只有一次。
With this solution, the input is parsed only once.
这篇关于Java:解析ISO_DATE / ISO_OFFSET_DATE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!