问题描述
我必须从字符串值中获取 OffsetDateTime
“2008-11-15T17:52:58”
我尝试了各种方法,但它给出了这个错误。请查看下面的代码片段和错误并提供注释。
第一种尝试方法:
zoneddatetime.parse("2008-11-15T17:52:58",DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).toOffsetDateTime();
第二次尝试:
OffsetDateTime.parse("2014-06-09T17:15:04+02:00",DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
我收到此错误。
Text '2008-11-15T17: 52: 58' Could not be parsed at index 19
解决方法
您的模式 yyyy-MM-dd'T'HH:mm:ss.SSSZ
不包含解析 +02:00
的区域偏移量。这种格式看起来像 RFC-3339,它已经在 DateTimeFormatter.ISO_DATE_TIME
如果你需要 OffsetDateTime
而你的输入没有偏移量,你应该问问自己使用什么偏移量。
DateTimeFormatter 中的 parseBest 方法可以尝试多个时态查询并将其返回给您:
Stream.of("2008-11-15T17:52:58","2014-06-09T17:15:04+02:00").map(s -> {
return DateTimeFormatter.ISO_DATE_TIME.parseBest(s,OffsetDateTime::from,LocalDateTime::from);
}).forEach(ta -> {
System.out.println("Type : " + ta.getClass());
System.out.println("Value : " + ta.toString());
});
这里是输出:
Type : class java.time.LocalDateTime
Value : 2008-11-15T17:52:58
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00
如您所见,您的第一个输入 2008-11-15T17:52:58
没有偏移信息,因此无法将其解析为 OffsetDateTime。如果您知道要使用的偏移量
.atOffset(...)
这是检测缺失偏移量并将LocalDateTime
转换为OffsetDateTime
的修改版本(如果你知道要使用什么偏移量)
Stream.of("2008-11-15T17:52:58",LocalDateTime::from);
}).forEach(ta -> {
final OffsetDateTime odt;
if (ta instanceof OffsetDateTime) {
odt = (OffsetDateTime) ta;
} else {
//here is 2-hour offset hardcoded. If you need OffsetDateTime
//you should also know offset somehow
odt = ((LocalDateTime) ta).atOffset(ZoneOffset.ofHours(2));
}
System.out.println("Type : " + odt.getClass());
System.out.println("Value : " + odt.toString());
});
输出
Type : class java.time.OffsetDateTime
Value : 2008-11-15T17:52:58+02:00
Type : class java.time.OffsetDateTime
Value : 2014-06-09T17:15:04+02:00
,
如果你能得到像 2014-06-09T17:15:04+02:00
这样的字符串,那么它包含一个 UTC 偏移量,这里是 +02:00
,即 2 小时 0 分钟。在这种情况下,您已设置:
OffsetDateTime parsedDateTime = OffsetDateTime.parse("2014-06-09T17:15:04+02:00");
System.out.println(parsedDateTime);
2014-06-09T17:15:04+02:00
我们甚至不需要指定格式化程序。该字符串采用 ISO 8601 格式,OffsetDateTime
和 java.time 的其他类将最常见的 ISO 8601 变体解析为它们的默认值。
如果您得到像 2008-11-15T17:52:58
这样的字符串,则偏移量丢失,因此无法直接将其转换为 OffsetDateTime
,因为顾名思义,{{ 1}} 包括一个偏移量。如果您只知道名字,则您不能为某人指定名字和姓氏。
如果您知道某些已知的时区已被理解和预期,您可以转换为 OffsetDateTime
,不过。如果你知道一个人的姓氏,也许你可以假设它也是这个人的姓氏?如果我们在代码中明确转换,可能更容易理解。我们首先解析为 OffsetDateTime
。 java.time 的某些类名中的 LocalDateTime
表示“没有时区或偏移量”,因此这是适合您的字符串的类。而且格式还是ISO 8601,所以我们还是不需要格式化程序。
Local
2008-11-15T17:52:58+05:00
转换会考虑指定时区的夏令时 (DST) 和其他时间变化。
您的代码出了什么问题?
OffsetDateTime calculatedDateTime = LocalDateTime.parse("2008-11-15T17:52:58")
.atZone(ZoneId.of("Asia/Karachi"))
.toOffsetDateTime();
System.out.println(calculatedDateTime);
您的模式 ZonedDateTime.parse("2008-11-15T17:52:58",DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).toOffsetDateTime();
要求您的字符串在秒上包含三位小数和一个不带冒号的 UTC 偏移量,例如 yyyy-MM-dd'T'HH:mm:ss.SSSZ
。看到这一点的一种方法是使用格式化程序进行格式化并打印结果:
2008-11-15T17:52:58.000+0200
2021-02-13T02:59:04.324+0530
由于您尝试解析的字符串既不包含秒的分数也不包含偏移量,因此解析失败。
您的第二次尝试遇到了同样的问题。您的字符串中仍然没有几分之一秒。这次有一个偏移量,但在小时和分钟之间有冒号,单个 System.out.println(ZonedDateTime.now(ZoneId.of("Asia/Kolkata"))
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")));
不匹配。您可能已将 Z
用于此类偏移。