【问题标题】:How to format the time as following "2018-03-15T23:47:15+01:00"如何将时间格式化为“2018-03-15T23:47:15+01:00”
【发布时间】:2018-03-14 18:29:38
【问题描述】:

使用 java.time ,我正在尝试将时间格式化为以下 "2018-03-15T23:47:15+01:00" 。 使用这个格式化程序,我接近 Scala 中的结果。

val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ")
ZonedDateTime.now() // 2018-03-14T19:25:23.397+01:00
ZonedDateTime.now().format(formatter) // => 2018-03-14 19:25:23+0100

但我不能在日期和小时之间插入额外的字符“T”。

顺便说一句,这个“T”是什么意思?

如何格式化为“2018-03-15T23:47:15+01:00”

注意事项:

如果您想知道为什么无法格式化 LocalDateTime Format LocalDateTime with Timezone in Java8

【问题讨论】:

    标签: scala datetime-format java-time


    【解决方案1】:

    试试这个

    val ZONED_DATE_TIME_ISO8601_FORMATTER3 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")
    
    ZonedDateTime.now().format(ZONED_DATE_TIME_ISO8601_FORMATTER3)
    // 2018-03-14T19:35:54.321+01:00
    

    here

    偏移 X 和 x:这会根据模式字母的数量来格式化偏移。一个字母仅输出小时,例如“+01”,除非分钟不为零,在这种情况下也会输出分钟,例如“+0130”。两个字母输出小时和分钟,不带冒号,如'+0130'。三个字母输出小时和分钟,带有冒号,例如'+01:30'。四个字母输出小时和分钟以及可选的秒,不带冒号,例如'+013015'。五个字母输出小时和分钟以及可选的秒,带有冒号,例如'+01:30:15'。六个或更多字母会引发 IllegalArgumentException。当要输出的偏移量为零时,模式字母“X”(大写)将输出“Z”,而模式字母“x”(小写)将输出“+00”、“+0000”或“+00” :00'。

    【讨论】:

    • 好的,插入 "special_char" 的技巧是 'special_char' 。 SSSxxx => +01:00 谢谢
    【解决方案2】:

    ZonedDateTime 转换为OffsetDateTime - 如其他答案中所建议的那样 - 有效,但如果您想使用DateTimeFormatter,则有一个内置常量可以完成这项工作:

    ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
    

    但重要的是要注意所有方法之间的一些差异。假设ZonedDateTime 包含与2018-03-15T23:47+01:00 等效的日期/时间(秒和毫秒为零)。

    答案中涵盖的所有方法都会给你不同的结果。

    toString() 在为零时省略秒和毫秒。所以这段代码:

    ZonedDateTime zdt = // 2018-03-15T23:47+01:00
    zdt.toOffsetDateTime().toString()
    

    打印:

    2018-03-15T23:47+01:00
    只有小时和分钟,因为秒和毫秒都是零

    如果它是零,内置格式化程序将只省略毫秒,但它会打印秒,无论值如何。所以这个:

    zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
    

    打印:

    2018-03-15T23:47:00+01:00
    打印秒数,即使它是零;省略毫秒

    使用显式模式的格式化程序将始终打印所有指定的字段,而不管它们的值如何。所以这个:

    zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"))
    

    打印:

    2018-03-15T23:47:00.000+01:00
    无论数值如何,都会打印秒和毫秒


    您还会发现2018-03-15T23:47:10.120+01:00 等值的差异(注意120 毫秒)。 toString()ofPattern 会给你:

    2018-03-15T23:47:10.120+01:00

    而内置的 DateTimeFormatter.ISO_OFFSET_DATE_TIME 将只打印前 2 位数字:

    2018-03-15T23:47:10.12+01:00

    在选择使用哪种方法时,请注意这些细节。

    【讨论】:

      【解决方案3】:

      正如您的问题已经表明的那样,您可能只是依靠ZonedDateTime.toString() 来获取像2018-03-14T19:25:23.397+01:00 这样的字符串。顺便说一句,该字符串采用国际标准 ISO 8601 格式。可能只需要进行两个小修改:

      • 如果您不想要秒的小数部分 - 好吧,我看不出它有什么害处,它符合 ISO 8601,因此收到您的 ISO 8601 字符串的人应该很高兴拥有它。但如果你不想要它,你可以申请myZonedDateTime.truncatedTo(ChronoUnit.SECONDS) 摆脱它。
      • ZonedDateTime.toString() 通常会附加一个区域名称,例如 2018-03-14T19:25:23+01:00[Europe/Paris],这不是 ISO 8601 标准的一部分。为避免这种情况,请在使用 toString 方法之前转换为 OffsetDateTimemyZonedDateTime.toOffsetDateTime().toString()(或 myZonedDateTime.truncatedTo(ChronoUnit.SECONDS).toOffsetDateTime().toString())。

      当您需要时,通过格式模式字符串构建您自己的格式化程序非常灵活。然而,很多时候我们可以用更少的东西来完成(然后应该这样做以使我们的代码更容易维护):toString 方法或内置格式化程序,包括我们可以从 DateTimeFormatter.ofLocalizedPattern() 获得的 ISO 和本地化格式化程序.

      顺便说一句,这个“T”是什么意思?

      T 是 ISO 8601 格式的一部分。它将日期部分与时间部分分开。您可以将其视为时间的 T,因为它表示时间部分的开始。如果只有日期 (2018-04-25) 或只有一天中的时间 (21:45:00),则不使用 T,但如果两者都有,则需要 T。您可能认为没有T 可能已经指定格式,您可能是对的。但是,对于周期/持续时间的格式,它是必不可少的,并且在没有天的情况下也需要:P3M 表示 3 个月的周期,而 PT3M 表示 3 分钟。

      链接:Wikipedia article on ISO 8601阅读更多内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-24
        • 2023-03-05
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多