你不能使用预定义的格式化程序,但是可以使用以下模式构建自己的格式化程序(并将其分配给静态常量):
static final DateTimeFormatter DATE_TIME_OPTIONAL_OFFSET =
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[xxx]")
注意:如果您解析的输入只包含日期和时间,但没有偏移量(也没有任何偏移量/区域默认值),那么结果只能是LocalDateTime
,而不是全局时间戳。
还请注意withZone(...)
方法的不同行为。
Joda-Time
When parsing, this zone will be set on the parsed datetime.
A null zone means of no-override. If both an override chronology
and an override zone are set, the override zone will take precedence
over the zone in the chronology.
Java-8 (JSR-310)
When parsing, there are two distinct cases to consider.
If a zone has been parsed directly from the text, perhaps because
DateTimeFormatterBuilder.appendZoneId() was used, then this override Zone
has no effect. If no zone has been parsed, then this override zone will
be included in the result of the parse where it can be used to build
instants and date-times.
顺便提一下:Joda-Time的方法withOffsetParsed()
更接近于Java-8的行为。
更新:我现在已经进行了自己的测试。请查看有时会令人惊讶的结果。
System.out.println(System.getProperty("java.version"))
// parsing s1 with offset = UTC
String s1 = "2015-01-01T12:29:22+00:00"
OffsetDateTime odt1 = DATE_TIME_OPTIONAL_OFFSET.parse(s1, OffsetDateTime::from)
System.out.println(odt1)
LocalDateTime ldt1 = DATE_TIME_OPTIONAL_OFFSET.parse(s1, LocalDateTime::from)
System.out.println(ldt1)
ZonedDateTime zdt1 = DATE_TIME_OPTIONAL_OFFSET.withZone(ZoneId.of("America/New_York")).parse(s1, ZonedDateTime::from)
System.out.println(zdt1)
// now parsing s2 without offset
String s2 = "2015-01-01T12:29:22"
OffsetDateTime odt2 = DATE_TIME_OPTIONAL_OFFSET.parse(s2, OffsetDateTime::from)
System.out.println(odt2)
LocalDateTime ldt2 = DATE_TIME_OPTIONAL_OFFSET.parse(s2, LocalDateTime::from)
System.out.println(ldt2)
DATE_TIME_OPTIONAL_OFFSET.withZone(ZoneId.of("America/New_York")).parse(s2, ZonedDateTime::from)
// throws an exception --- seems to be a bug compared with the spec above, the zone set was not accepted
结论:
在迁移时要小心。魔鬼就在细节中。也许更新的Java版本8u40已经修复了一些问题(至少withZone()
的行为可能已经得到了纠正-请参见JDK-issue 8033662,但对于8u31,回退修复似乎缺失?!)。您还应该注意,在我的测试中,标记为“EST”的“时区”已被替换为“America / New_York”,因为“EST”不是一个被认可的时区ID(它只是美国本地化的时区名称缩写)。
更新-最终解决方案
经过额外的测试,此代码似乎在Java 8u31中运行良好(假设默认情况下为UTC,如果输入中缺少偏移量):
static final DateTimeFormatter DATE_TIME_OPTIONAL_OFFSET =
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[xxx]")
OffsetDateTime odt =
DATE_TIME_OPTIONAL_OFFSET.withZone(ZoneOffset.UTC).parse(input, OffsetDateTime::from)
ZonedDateTime zdt = odt.toZonedDateTime()