sil*_*box 5 datetime iso8601 datetime-parsing java-8 java-time
我的应用程序应该能够解析忽略时区的日期(我总是知道它是UTC).问题是日期可能会出现以下两种形式 -
2017-09-11T12:44:07.793Z
0001-01-01T00:00:00
我可以解析第一个使用LocalDateTime
,第二个使用Instant
类.有没有办法使用单一机制?
PS我试图避免Z
输入字符串末尾的硬编码
小智 6
如果Z
偏移是可选的,则可以使用java.time.format.DateTimeFormatterBuilder
带可选部分的a:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter
.toFormatter();
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用该parseBest
方法,以及TemporalQuery
尝试创建对应对象的列表.然后检查返回类型并采取相应措施:
Instant instant = null;
// tries to create Instant, and if it fails, try a LocalDateTime
TemporalAccessor parsed = fmt.parseBest("2017-09-11T12:44:07.793Z", Instant::from, LocalDateTime::from);
if (parsed instanceof Instant) {
instant = (Instant) parsed;
} else if (parsed instanceof LocalDateTime) {
// convert LocalDateTime to UTC instant
instant = ((LocalDateTime) parsed).atOffset(ZoneOffset.UTC).toInstant();
}
System.out.println(instant); // 2017-09-11T12:44:07.793Z
Run Code Online (Sandbox Code Playgroud)
使用第二个输入(0001-01-01T00:00:00
)运行产生Instant
等效于0001-01-01T00:00:00Z
.
另外,在上述的例子中,我只是用Instant::from
和LocalDateTime::from
,所以格式化试图首先创建一个Instant
.如果它不可能,那么它会尝试创建一个LocalDateTime
.您可以向该列表添加任意数量的类型(例如,我可以添加ZonedDateTime::from
,如果ZonedDateTime
创建了一个,我可以转换为Instant
使用toInstant()
方法).
如您所知,输入始终为UTC,您也可以直接在格式化程序中进行设置:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter with UTC
.toFormatter().withZone(ZoneOffset.UTC);
Run Code Online (Sandbox Code Playgroud)
所以你可以直接解析它Instant
:
System.out.println(Instant.from(fmt.parse("2017-09-11T12:44:07.793Z"))); // 2017-09-11T12:44:07.793Z
System.out.println(Instant.from(fmt.parse("0001-01-01T00:00:00"))); // 0001-01-01T00:00:00Z
Run Code Online (Sandbox Code Playgroud)