[英]Converting ISO 8601-compliant String to ZonedDateTime
I'm parsing logs from different sources, I'm extracting datetime string from log.我正在解析来自不同来源的日志,我正在从日志中提取日期时间字符串。 Now I want to convert it into java ZonedDateTime.
现在我想把它转换成 java ZonedDateTime。
Problem here is, I don't know exact datetime format, I just know that, string will be ISO-8601 compliant.这里的问题是,我不知道确切的日期时间格式,我只知道,字符串将符合 ISO-8601。 So I want to write function like:
所以我想像这样写 function :
/**
* @param _dateTime : any ISO 8601 format , e.g 1. %Y-%m-%dT%H:%M:%s%z => 2014-05-25T08:20:03.123456Z ,
* e.g 2. %Y-%m-%dT%H:%M:%s => 2014-05-25T08:20:03.123456, e.g 3. %Y-%m-%d %H:%M:%s%z => 2014-11-08 15:55:55.123456Z,
* e.g 4. %Y-%m-%d %H:%M:%s => 2014-11-08 15:55:55
* @return Instance of ZonedDateTime if conversion successful
* @throws DateTimeParseException
*/
private ZonedDateTime parse (String _dateTime) throws DateTimeParseException {
// Magic here.
}
What is best way to do it in java?在 java 中最好的方法是什么?
That's non-trivial alright.这不是微不足道的好吧。 Most of the magic is in the following formatter:
大多数魔法都在以下格式化程序中:
private static final DateTimeFormatter formatter
= new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendPattern("['T'][' ']")
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.appendPattern("[XX]")
.toFormatter();
This formatter accepts此格式化程序接受
2014-05-25
.2014-05-25
这样的日期。T
or a space (or both or neither, but I count on exactly one of them being in your string).T
或一个空格(或两者或两者都没有,但我指望它们中的一个恰好在你的字符串中)。 The square brackets denote optional parts of the format.T
not to be interpreted as a pattern letter.T
不被解释为模式字母。ISO_LOCAL_TIME
accepts seconds with and without a decimal fraction. ISO_LOCAL_TIME
接受带和不带小数的秒。Z
(for zero) or -0600
.Z
(为零)或-0600
。 We also need a time zone for the cases where we haven't got an offset in the string.对于字符串中没有偏移量的情况,我们还需要一个时区。 For example:
例如:
private static final ZoneId defaultZone = ZoneId.of("America/Curacao");
What your method still needs to do is distinguish between the cases with and without UTC offset.您的方法仍然需要做的是区分有和没有 UTC 偏移的情况。 The form with offset can be parsed directly into a
ZonedDateTime
.带有偏移量的表单可以直接解析为
ZonedDateTime
。 The one without cannot, so for it we need to parse into a LocalDateTime
and convert.没有的不能,所以我们需要解析成
LocalDateTime
并转换。
/**
* @param dateTime : any ISO 8601 format , e.g 1. %Y-%m-%dT%H:%M:%s%z => 2014-05-25T08:20:03.123456Z ,
* e.g 2. %Y-%m-%dT%H:%M:%s => 2014-05-25T08:20:03.123456,
* e.g 3. %Y-%m-%d %H:%M:%s%z => 2014-11-08 15:55:55.123456Z,
* e.g 4. %Y-%m-%d %H:%M:%s => 2014-11-08 15:55:55
* @return Instance of ZonedDateTime if conversion successful
* @throws DateTimeParseException
*/
private static ZonedDateTime parse(String dateTime) {
// Little magic here.
TemporalAccessor parsed = formatter.parseBest(dateTime,
ZonedDateTime::from, LocalDateTime::from);
if (parsed instanceof ZonedDateTime) {
return (ZonedDateTime) parsed;
} else {
return ((LocalDateTime) parsed).atZone(defaultZone);
}
}
Let's try it out.让我们试试看。 I have used your four examples plus one that I added between the 1st and the 2nd.
我已经使用了你的四个例子,加上我在第一个和第二个之间添加的一个。
System.out.println(parse("2014-05-25T08:20:03.123456Z"));
System.out.println(parse("2014-05-25T10:20:03.123456+0200"));
System.out.println(parse("2014-05-25T08:20:03.123456"));
System.out.println(parse("2014-11-08 15:55:55.123456Z"));
System.out.println(parse("2014-11-08 15:55:55"));
Output: Output:
2014-05-25T08:20:03.123456Z 2014-05-25T10:20:03.123456+02:00 2014-05-25T08:20:03.123456-04:00[America/Curacao] 2014-11-08T15:55:55.123456Z 2014-11-08T15:55:55-04:00[America/Curacao]
As an aside prefer OffsetDateTime
over ZonedDateTime
for your strings with a UTC offset.顺便说一句,对于带有 UTC 偏移量的字符串,更喜欢
OffsetDateTime
而不是ZonedDateTime
。 The code will be the same except you will need a further conversion .toOffsetDateTime()
after atZone(defaultZone)
in the case where you don't get an OffsetDateTime
directly from parsing.代码将是相同的,除非您需要在
atZone(defaultZone)
) 之后进一步转换.toOffsetDateTime()
在您没有直接从解析中获得OffsetDateTime
的情况下。 A ZonedDateTime
is for a date and time with a time zone like Europe/Prague. ZonedDateTime
用于日期和时间,时区如欧洲/布拉格。 An OffsetDateTime
is for a date and time with a UTC offset. OffsetDateTime
用于具有 UTC 偏移量的日期和时间。 As I mentioned, Z
is an offset of 0 from UTC.正如我所提到的,
Z
与 UTC 的偏移量为 0。
Edit: Arvind Kumar Avinash' notes in a comment are useful and important enough to deserve to be in the answer proper: Some notes for the future visitors:编辑:Arvind Kumar Avinash 在评论中的注释非常有用和重要,值得正确回答:给未来访客的一些注释:
[XX]
with [XX][XXX]
will also cater to the offset like +02:00.[XX]
替换为[XX][XXX]
也将满足 +02:00 之类的偏移量。.toFormatter(Locale.ENGLISH)
instead of .toFormatter()
..toFormatter(Locale.ENGLISH)
而不是.toFormatter()
。ZoneId.systemDefault()
if you want the ZoneId
of the JVM to be picked up automatically.ZoneId
的 ZoneId 被自动拾取,您可以使用ZoneId.systemDefault()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.