【问题标题】:Java DateTimeFormatter for time zone with an optional colon separator?带有可选冒号分隔符的时区的Java DateTimeFormatter?
【发布时间】:2016-01-06 16:11:50
【问题描述】:

我正在尝试构建一个 DateTimeFormatter,它可以接受带冒号的偏移量或不带冒号的偏移量。

有没有办法通过这个测试:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[X]");
dateTimeFormatter.parse("2015-01-28T10:21:44+0100"); // OK
dateTimeFormatter.parse("2015-01-28T10:21:44+01:00"); // KO

【问题讨论】:

  • 您认为可选的冒号是区域偏移部分的固定部分。您只能在模式字母 X(不带冒号)或 XXX(带冒号)之间进行选择。这意味着整个区域偏移是可选的,而不仅仅是里面的冒号。
  • 我同意,它应该可以工作。但是当我使用 [X] 时,它需要一个不带冒号的偏移量,而当我使用 [XXX] 时,它需要一个带冒号的偏移量。我不能同时使用两者。
  • 根据Javadoc:用符号X给出这些例子:Z; -08; -0830; -08:30; -083015; -08:30:15;
  • 请阅读 javadoc 部分“偏移 X 和 x”。它精确地描述了字母 X,x 的数量与哪种格式表示相关联。所以我们有:XX(不带冒号)和 XXX(带冒号)。 X(不带冒号)使分钟部分是可选的。

标签: java datetime java-time


【解决方案1】:

这个:yyyy-MM-dd'T'HH:mm:ss[XXX][X] 似乎有效。

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[XXX][X]");
dateTimeFormatter.parse("2015-01-28T10:21:44+0100");
dateTimeFormatter.parse("2015-01-28T10:21:44+01:00");

【讨论】:

  • 是的,它有效!我试过 [X][XXX](不起作用)但不是 [XXX][X]。谢谢!
  • 一个奇异的方面:如果输入包含两个偏移量,那么这也可能被解析。
【解决方案2】:

这是看起来像 ISO 字符串日期的所有内容的终极模式匹配!

"[yyyyMMdd][yyyy-MM-dd][yyyy-DDD]['T'[HHmmss][HHmm][HH:mm:ss][HH:mm][.SSSSSSSSS][.SSSSSS][.SSS][.SS][.S]][OOOO][O][z][XXXXX][XXXX]['['VV']']"

它适用于以下测试列表,除了 cmets 中的两个,但我仍然不知道为什么......

    ZonedDateTime dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+020000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0200[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993Z[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993GMT+1[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993UTC[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993PST[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993[Europe/Paris]");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+020000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0200[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08Z[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08GMT+1[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08UTC[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08PST[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08[Europe/Paris]");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+020000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0200");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993Z");
    //dt = DateTimeUtils.parse("2016-10-27T16:36:08.993GMT+1");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993UTC");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993PST");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.000993");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.000000993");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+020000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0200");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08Z");
    //dt = DateTimeUtils.parse("2016-10-27T16:36:08GMT+1");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08UTC");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08PST");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08");

    dt = DateTimeUtils.parse("2016-100T16:36:08Z");
    dt = DateTimeUtils.parse("2016-100T16:36.1Z");
    dt = DateTimeUtils.parse("2016-10-27");

    dt = DateTimeUtils.parse("20161223T163608");
    dt = DateTimeUtils.parse("20161223T1636");

还有解析方法本身:

public static ZonedDateTime parse(CharSequence text) {
    TemporalAccessor temporalAccessor = LOOSE_ISO_DATE_TIME_ZONE_PARSER.parseBest(text, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
    if (temporalAccessor instanceof ZonedDateTime) {
        return ((ZonedDateTime) temporalAccessor);
    }
    if (temporalAccessor instanceof LocalDateTime) {
        return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault());
    }
    return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault());
}

【讨论】:

  • 我假设它不适用于评论中的人,因为您在 GMT 之后没有满足“+1”的需求。诚然,我不认识这些表达方式,但似乎在任何地方都不适合“+”号?
  • 它应该可以识别整个 GMT+1,就像 2016-10-27T16:36:08.993GMT+1[Europe/Paris] 一样。
  • 好的 - 欧洲/巴黎以文本/插入符号结束,而那些不工作的以“+1”结束 - 我可能在那里:)
  • 几乎完美,但是,当偏移量不带冒号时,解析不会以错​​误结束,但无法识别偏移量,这里的输出为“2016-10-27T16:36:08.993+ 020000" ==> 2016-10-27T16:36:08.993Z,我猜这是一个解析器问题,再调查一下。
  • 这里是DateTimeFormatterBuilder 文档。你可以知道XXXXVV是什么意思,等等。
猜你喜欢
  • 2011-01-23
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 2013-03-10
相关资源
最近更新 更多