java.time DateTimeFormatter模式,用于时区偏移

时间:2015-06-08 13:45:51

标签: java date parsing formatter java-time

我正在尝试解析:2014-05-02-10.45.05.993280-5:00其中-5:00是与UTC的偏移量。在Java 8中使用java.time DateTimeFormatter

对于第一位,我有以下内容:yyyy-MM-dd-HH.mm.ss.SSSSSS但是,我无法弄清楚解析偏移量的模式应该是什么。

如果我有4位数(-05:00)的偏移量,我可以使用:yyyy-MM-dd-HH.mm.ss.SSSSSSxxx,但这不适用于3位数。

有什么想法吗?

3 个答案:

答案 0 :(得分:17)

使用大写字母X代替x,因此使用XXX。区别在于大X可以识别输入字母" Z"作为UTC-Offset +00:00,而小图案字母X不能。

建议模式:

yyyy-MM-dd-HH.mm.ss.SSSSSSXXX

请注意以下JDK-bug

  

java.time.format.DateTimeFormatter无法使用single解析偏移量   数字小时

<强>更新

我现在已经在错误日志中测试了所描述的解决方法。

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));

但它引发了一个例外:

  

线程中的异常&#34; main&#34; java.time.format.DateTimeParseException:   文字&#39; 2014-05-02-10.45.05.993280-5:00&#39;无法在索引26处解析     at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)     at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)     在HelloWorld.main(HelloWorld.java:16)

所以宽松的解析也没有帮助。 所以现在只剩下三个选项:

  • 使用bug报告器建议的解决方法:[...]解决方法是分别解析日期/时间,使用手动编码解析器进行偏移,并将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修复,但Java-8的后端似乎不可用。

答案 1 :(得分:3)

SimpleDateFormat符号偏移 Z 检查Java7Java8 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

答案 2 :(得分:2)

所有答案都很好。 java8+ 有以下模式来解析和格式化时区:VzOXxZ

根据文档中的规则,它们是解析

   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.Datejava.util.Calendar - 并非所有类型都能正常工作,因为这些类型已损坏(因此标记为已弃用,请不要使用它们)