将没有 ZonedId 的字符串转换为 OffsetDateTime
Convert String without ZonedId to OffsetDateTime
我想将 String 转换为 OffsetDateTime 数据类型。该字符串具有以下形状:
2017-11-27T19:06:03
我试过两种方法:
方法一
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.toFormatter();
return OffsetDateTime.parse(timestamp, formatter);
}
方法二:
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter parser = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
java.time.LocalDateTime dt = java.time.LocalDateTime.parse(timestamp, parser);
ZonedDateTime zdt = ZonedDateTime.of(dt, java.time.ZoneId.of("UTC"));
return OffsetDateTime.from(zdt);
}
第一种方法无效,因为它会抱怨以下内容:
java.time.format.DateTimeParseException: Text '2017-11-27T19:02:42' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2017-11-27T19:02:42 of type java.time.format.Parsed
据我了解,这是因为字符串没有 ZoneId。我怎样才能在格式化程序上覆盖 ZoneId 以便忽略它?
第二种方法 有效,但它需要 2 次额外的转换,我想避免这些额外的转换。
我们将不胜感激。
最后,我通过以下代码解决了这个问题:
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.toFormatter();
return LocalDateTime.parse(timestamp, formatter)
.atOffset(java.time.ZoneOffset.UTC);
}
要从没有偏移量或时区的字符串中获取 OffsetDateTime
,您需要确定偏移量或获取偏移量的方法。最明显的方法是,如果您知道要在哪个时区解释日期时间。例如:
OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
.atZone(ZoneId.of("Asia/Chongqing"))
.toOffsetDateTime();
System.out.println(dateTime);
使用问题中的字符串输出:
2017-11-27T19:06:03+08:00
不要害怕从LocalDateTime
到ZonedDateTime
再到OffsetDateTime
的两次转换。使用 java.time
,它们不仅易于操作,而且清晰易读。
如果您知道偏移量,只需使用它,那么您只需要一次转换(我在示例中使用了一个无意义的偏移量,因此您必须自己选择):
OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
.atOffset(ZoneOffset.ofTotalSeconds(-36953));
System.out.println(dateTime);
输出:
2017-11-27T19:06:03-10:15:53
您可以指定所需的偏移量,例如 ZoneOffset.of("+08:00")
或 ZoneOffset.ofHours(8)
。
但是回答你的问题(现在是时候了)。
How can I overwrite, on the formatter, the ZoneId so to ignore it?
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.parseDefaulting(ChronoField.OFFSET_SECONDS, -36953)
.toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(timestamp, formatter);
System.out.println(dateTime);
输出与上一个相同(您需要再次选择适合您情况的偏移量)。
我想将 String 转换为 OffsetDateTime 数据类型。该字符串具有以下形状:
2017-11-27T19:06:03
我试过两种方法:
方法一
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.toFormatter();
return OffsetDateTime.parse(timestamp, formatter);
}
方法二:
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter parser = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
java.time.LocalDateTime dt = java.time.LocalDateTime.parse(timestamp, parser);
ZonedDateTime zdt = ZonedDateTime.of(dt, java.time.ZoneId.of("UTC"));
return OffsetDateTime.from(zdt);
}
第一种方法无效,因为它会抱怨以下内容:
java.time.format.DateTimeParseException: Text '2017-11-27T19:02:42' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2017-11-27T19:02:42 of type java.time.format.Parsed
据我了解,这是因为字符串没有 ZoneId。我怎样才能在格式化程序上覆盖 ZoneId 以便忽略它?
第二种方法
我们将不胜感激。
最后,我通过以下代码解决了这个问题:
public static OffsetDateTime convertString(String timestamp) {
java.time.format.DateTimeFormatter formatter = new java.time.format.DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.toFormatter();
return LocalDateTime.parse(timestamp, formatter)
.atOffset(java.time.ZoneOffset.UTC);
}
要从没有偏移量或时区的字符串中获取 OffsetDateTime
,您需要确定偏移量或获取偏移量的方法。最明显的方法是,如果您知道要在哪个时区解释日期时间。例如:
OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
.atZone(ZoneId.of("Asia/Chongqing"))
.toOffsetDateTime();
System.out.println(dateTime);
使用问题中的字符串输出:
2017-11-27T19:06:03+08:00
不要害怕从LocalDateTime
到ZonedDateTime
再到OffsetDateTime
的两次转换。使用 java.time
,它们不仅易于操作,而且清晰易读。
如果您知道偏移量,只需使用它,那么您只需要一次转换(我在示例中使用了一个无意义的偏移量,因此您必须自己选择):
OffsetDateTime dateTime = LocalDateTime.parse(timestamp)
.atOffset(ZoneOffset.ofTotalSeconds(-36953));
System.out.println(dateTime);
输出:
2017-11-27T19:06:03-10:15:53
您可以指定所需的偏移量,例如 ZoneOffset.of("+08:00")
或 ZoneOffset.ofHours(8)
。
但是回答你的问题(现在是时候了)。
How can I overwrite, on the formatter, the ZoneId so to ignore it?
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.parseDefaulting(ChronoField.OFFSET_SECONDS, -36953)
.toFormatter();
OffsetDateTime dateTime = OffsetDateTime.parse(timestamp, formatter);
System.out.println(dateTime);
输出与上一个相同(您需要再次选择适合您情况的偏移量)。