我有各种格式的时间戳,例如:
2018-07-21T00:50:39
2017-11-20T23:18:27.529Z
我需要将它们解析为java.util.Date,并尝试了以下方法,它们都适用于第一种格式但未通过第二种格式。
这是我尝试的方法,它是错误的:
1.
private Date try3(String dateString) {
return Date.from(Instant.parse(dateString).atZone(ZoneId.of("UTC")).toInstant());
}
它以第一种格式失败,错误:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:28' could not be parsed at index 19
2.
private Date try2(String dateString) {
return Date.from(LocalDateTime.parse(dateString).atZone(ZoneId.of("UTC")).toInstant());
}
对于第二种格式,此方法抛出错误:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:27.529Z' could not be parsed, unparsed text found at index 23
3:
private Date try1(String dateString) {
return Date.from(ZonedDateTime.parse(dateString,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(ZoneId.of("UTC"))).toInstant());
}
对于第二种格式,上面的方法抛出错误:
java.time.format.DateTimeParseException: Text '2017-11-20T23:18:27.529Z' could not be parsed, unparsed text found at index 19
我最终最终得到了Joda库:
private Date try4(String dateString) {
return new DateTime(dateString).withZone(DateTimeZone.UTC).toDate();
}
但是在Java时间库中真的有办法做到这一点吗?
你总是希望获得相同的类型,我似乎明白如果字符串中没有偏移量,你需要UTC(重要的是要清楚这一点)。我建议如果字符串中没有任何偏移量,请指定一个带有可选UTC偏移量和默认值UTC(零偏移量)的格式化程序:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("[X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
String withoutZ = "2018-07-21T00:50:39";
Instant anInstant = formatter.parse(withoutZ, Instant::from);
System.out.println(anInstant);
String withZ = "2017-11-20T23:18:27.529Z";
Instant anotherInstant = formatter.parse(withZ, Instant::from);
System.out.println(anotherInstant);
输出:
2018-07-21T00:50:39Z 2017-11-20T23:18:27.529Z
格式模式字符串[X]
中的方括号表示偏移量X是可选的。 ISO_LOCAL_DATE_TIME
处理秒数的存在和不存在。
我希望你知道Date
类的设计很差并且已经过时了,所以通常你不应该想要一个,而且你只需要一个,因为你不可避免地需要一个你现在无法改变的遗留API。在这种情况下,如你的问题那样从Instant
进行最终转换。
通常用于可变日期/时间格式的技术包括:
.endsWith("Z")
上分支,正如Basil Bourque的回答中所建议的那样。DateTimeFormatterBuilder.parseDefaulting()
用于解析后的字符串中可能不存在的部分。DateTimeFormatter.parseBest()
。如您所见,我在这里使用第3项和第4项。
这已经被无数次覆盖了。因此,请搜索Stack Overflow以获取更多信息。
切勿使用Date
或Calendar
。仅使用java.time。同样,Joda-Time也被java.time取代(两者都由同一个人Stephen Colebourne领导)。
您的字符串输入都是标准的ISO 8601格式。在解析/生成字符串时,java.time类默认使用这些格式。
第一个缺少从UTC或时区偏移的指标,因此它不代表片刻。
LocalDateTime.parse( "2018-07-21T00:50:39" )
Z
中的第二个意思是UTC,发音为“Zulu”。
Instant.parse( "2017-11-20T23:18:27.529Z" )
要在一个方法中处理这两种格式,请在输入字符串中搜索Z
的存在并相应地进行分支。此外,如果您收到意外输入,请捕获异常。
如果你必须有一个java.util.Date
对象,请在转换为java.time类或从java.time类转换的旧类中查看用于新方法from
和to…
的类JavaDoc。正如我所说,所有这些已被覆盖很多次,所以搜索更多信息。