java.time 时区偏移的 DateTimeFormatter 模式
java.time DateTimeFormatter pattern for timezone offset
我正在尝试解析:2014-05-02-10.45.05.993280-5:00
其中 -5:00
是与 UTC 的偏移量。在 Java 中使用 java.time DateTimeFormatter
8.
对于第一位,我有以下内容:yyyy-MM-dd-HH.mm.ss.SSSSSS
但是,我也不知道解析偏移量的模式应该是什么。
如果我有 4 位数字的偏移量 (-05:00),我可以使用:yyyy-MM-dd-HH.mm.ss.SSSSSSxxx
,但这不适用于 3 位数字。
有什么想法吗?
SimpleDateFormat
符号的偏移量是 Z
检查 Java7
or Java8
SimpleDateFormat API
.
然后,String
的解析器格式
2014-05-02-10.45.05.993280-5:00
必须是:
yyyy-MM-dd-HH.mm.ss.SSSSSSZ
更新:对于DateTimeFormatter
,偏移量格式化和解析模式是:
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
您在 DateTimeFormatter
中想要的模式是 X
.
使用大写字母 X 而不是 x,因此是 XXX。区别在于大X可以将输入字母“Z”识别为UTC-Offset +00:00,而小模式字母X不能。
建议模式:
yyyy-MM-dd-HH.mm.ss.SSSSSSXXX
还请注意以下内容JDK-bug:
java.time.format.DateTimeFormatter cannot parse an offset with single
digit hour
更新:
我现在已经测试了错误日志中描述的解决方法。
String input = "2014-05-02-10.45.05.993280-5:00";
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS")
.parseLenient()
.appendOffset("+HH:MM", "Z")
.toFormatter();
System.out.println(f.parse(input, ZonedDateTime::from));
但是抛出异常:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '2014-05-02-10.45.05.993280-5:00' could not be parsed at index 26
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at HelloWorld.main(HelloWorld.java:16)
所以宽松的解析也无济于事。 所以现在只剩下三个选项给你了:
使用 bug 报告者建议的解决方法:[...] 解决方法是单独解析 date/time,使用手动编码的解析器作为偏移量,并将 LocalDateTime 与手动解析的方法结合起来抵消。不是一件容易的事。
尝试您自己的专门字符串预处理。如果你有一个固定的格式那么你可以尝试在位置 26 插入零数字(如果总输入长度是一个数字太小)。
或者您使用可以执行此操作的外部库。如果您愿意添加额外的依赖项,我的库 Time4J (v4.0) 可以做到这一点。请参阅此代码:
String input = "2014-05-02-10.45.05.993280-5:00";
ZonalDateTime zdt =
ZonalDateTime.parse(
input,
Moment.localFormatter("yyyy-MM-dd-HH.mm.ss.SSSSSSXXX", PatternType.CLDR));
System.out.println(zdt); // 2014-05-02T10:45:05,993280UTC-05:00
ZonedDateTime result = zdt.toTemporalAccessor();
更新: 根据 JDK-bug-status,错误已修复 Java-9,但 [=57 的反向移植=]-8 似乎不可用。
所有答案都很好。 java8+ 具有以下用于解析和格式化时区的模式:V
、z
、O
、X
、x
、Z
.
根据文档中的规则,解析,它们是:
Symbol Meaning Presentation Examples
------ ------- ------------ -------
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
但是格式化怎么样?
这是一个日期示例(假设 ZonedDateTime
),它显示了不同格式模式的这些模式行为:
// The helper function:
static void printInPattern(ZonedDateTime dt, String pattern) {
System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
}
// The date:
String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
// 2020-11-03T16:40:44-08:00[America/Los_Angeles]
// Rules:
// printInPattern(dt, "V"); // exception!
printInPattern(dt, "VV"); // America/Los_Angeles
// printInPattern(dt, "VVV"); // exception!
// printInPattern(dt, "VVVV"); // exception!
printInPattern(dt, "z"); // PST
printInPattern(dt, "zz"); // PST
printInPattern(dt, "zzz"); // PST
printInPattern(dt, "zzzz"); // Pacific Standard Time
printInPattern(dt, "O"); // GMT-8
// printInPattern(dt, "OO"); // exception!
// printInPattern(dt, "OO0"); // exception!
printInPattern(dt, "OOOO"); // GMT-08:00
printInPattern(dt, "X"); // -08
printInPattern(dt, "XX"); // -0800
printInPattern(dt, "XXX"); // -08:00
printInPattern(dt, "XXXX"); // -0800
printInPattern(dt, "XXXXX"); // -08:00
printInPattern(dt, "x"); // -08
printInPattern(dt, "xx"); // -0800
printInPattern(dt, "xxx"); // -08:00
printInPattern(dt, "xxxx"); // -0800
printInPattern(dt, "xxxxx"); // -08:00
printInPattern(dt, "Z"); // -0800
printInPattern(dt, "ZZ"); // -0800
printInPattern(dt, "ZZZ"); // -0800
printInPattern(dt, "ZZZZ"); // GMT-08:00
printInPattern(dt, "ZZZZZ"); // -08:00
在正偏移的情况下,到处都使用 +
符号字符(现在有 -
)并且从不省略。
这适用于新的 java.time
类型。如果您打算将它们用于 java.util.Date
或 java.util.Calendar
- 并非所有类型都有效,因为这些类型已损坏(因此标记为已弃用,请不要使用它们)
我正在尝试解析:2014-05-02-10.45.05.993280-5:00
其中 -5:00
是与 UTC 的偏移量。在 Java 中使用 java.time DateTimeFormatter
8.
对于第一位,我有以下内容:yyyy-MM-dd-HH.mm.ss.SSSSSS
但是,我也不知道解析偏移量的模式应该是什么。
如果我有 4 位数字的偏移量 (-05:00),我可以使用:yyyy-MM-dd-HH.mm.ss.SSSSSSxxx
,但这不适用于 3 位数字。
有什么想法吗?
SimpleDateFormat
符号的偏移量是 Z
检查 Java7
or Java8
SimpleDateFormat API
.
然后,String
2014-05-02-10.45.05.993280-5:00
必须是:
yyyy-MM-dd-HH.mm.ss.SSSSSSZ
更新:对于DateTimeFormatter
,偏移量格式化和解析模式是:
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
您在 DateTimeFormatter
中想要的模式是 X
.
使用大写字母 X 而不是 x,因此是 XXX。区别在于大X可以将输入字母“Z”识别为UTC-Offset +00:00,而小模式字母X不能。
建议模式:
yyyy-MM-dd-HH.mm.ss.SSSSSSXXX
还请注意以下内容JDK-bug:
java.time.format.DateTimeFormatter cannot parse an offset with single digit hour
更新:
我现在已经测试了错误日志中描述的解决方法。
String input = "2014-05-02-10.45.05.993280-5:00";
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS")
.parseLenient()
.appendOffset("+HH:MM", "Z")
.toFormatter();
System.out.println(f.parse(input, ZonedDateTime::from));
但是抛出异常:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2014-05-02-10.45.05.993280-5:00' could not be parsed at index 26 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at HelloWorld.main(HelloWorld.java:16)
所以宽松的解析也无济于事。 所以现在只剩下三个选项给你了:
使用 bug 报告者建议的解决方法:[...] 解决方法是单独解析 date/time,使用手动编码的解析器作为偏移量,并将 LocalDateTime 与手动解析的方法结合起来抵消。不是一件容易的事。
尝试您自己的专门字符串预处理。如果你有一个固定的格式那么你可以尝试在位置 26 插入零数字(如果总输入长度是一个数字太小)。
或者您使用可以执行此操作的外部库。如果您愿意添加额外的依赖项,我的库 Time4J (v4.0) 可以做到这一点。请参阅此代码:
String input = "2014-05-02-10.45.05.993280-5:00";
ZonalDateTime zdt =
ZonalDateTime.parse(
input,
Moment.localFormatter("yyyy-MM-dd-HH.mm.ss.SSSSSSXXX", PatternType.CLDR));
System.out.println(zdt); // 2014-05-02T10:45:05,993280UTC-05:00
ZonedDateTime result = zdt.toTemporalAccessor();
更新: 根据 JDK-bug-status,错误已修复 Java-9,但 [=57 的反向移植=]-8 似乎不可用。
所有答案都很好。 java8+ 具有以下用于解析和格式化时区的模式:V
、z
、O
、X
、x
、Z
.
根据文档中的规则,解析,它们是:
Symbol Meaning Presentation Examples
------ ------- ------------ -------
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
但是格式化怎么样?
这是一个日期示例(假设 ZonedDateTime
),它显示了不同格式模式的这些模式行为:
// The helper function:
static void printInPattern(ZonedDateTime dt, String pattern) {
System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
}
// The date:
String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
// 2020-11-03T16:40:44-08:00[America/Los_Angeles]
// Rules:
// printInPattern(dt, "V"); // exception!
printInPattern(dt, "VV"); // America/Los_Angeles
// printInPattern(dt, "VVV"); // exception!
// printInPattern(dt, "VVVV"); // exception!
printInPattern(dt, "z"); // PST
printInPattern(dt, "zz"); // PST
printInPattern(dt, "zzz"); // PST
printInPattern(dt, "zzzz"); // Pacific Standard Time
printInPattern(dt, "O"); // GMT-8
// printInPattern(dt, "OO"); // exception!
// printInPattern(dt, "OO0"); // exception!
printInPattern(dt, "OOOO"); // GMT-08:00
printInPattern(dt, "X"); // -08
printInPattern(dt, "XX"); // -0800
printInPattern(dt, "XXX"); // -08:00
printInPattern(dt, "XXXX"); // -0800
printInPattern(dt, "XXXXX"); // -08:00
printInPattern(dt, "x"); // -08
printInPattern(dt, "xx"); // -0800
printInPattern(dt, "xxx"); // -08:00
printInPattern(dt, "xxxx"); // -0800
printInPattern(dt, "xxxxx"); // -08:00
printInPattern(dt, "Z"); // -0800
printInPattern(dt, "ZZ"); // -0800
printInPattern(dt, "ZZZ"); // -0800
printInPattern(dt, "ZZZZ"); // GMT-08:00
printInPattern(dt, "ZZZZZ"); // -08:00
在正偏移的情况下,到处都使用 +
符号字符(现在有 -
)并且从不省略。
这适用于新的 java.time
类型。如果您打算将它们用于 java.util.Date
或 java.util.Calendar
- 并非所有类型都有效,因为这些类型已损坏(因此标记为已弃用,请不要使用它们)