使用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"是指BTW?
如何格式化为" 2018-03-15T23:47:15 + 01:00" ?
注意:
如果你想知道为什么LocalDateTime
无法格式化
Format LocalDateTime with Timezone in Java8
答案 0 :(得分:3)
试试这个
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'
答案 1 :(得分:1)
将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
只会打印前两位数字:
2018-03-15T23:47:10.12 + 01:00
在选择使用哪种方法时,请注意这些细节。
答案 2 :(得分:0)
正如您的问题已经显示的那样,您可能只需依靠ZonedDateTime.toString()
来获取2018-03-14T19:25:23.397+01:00
之类的字符串。顺便说一句,该字符串是ISO 8601格式,国际标准。只需要进行两处小修改:
myZonedDateTime.truncatedTo(ChronoUnit.SECONDS)
来摆脱它。ZonedDateTime.toString()
经常附加区域名称,例如2018-03-14T19:25:23+01:00[Europe/Paris]
,这不是ISO 8601标准的一部分。为避免这种情况,请在使用其 OffsetDateTime
方法之前转换为toString
:myZonedDateTime.toOffsetDateTime().toString()
(或myZonedDateTime.truncatedTo(ChronoUnit.SECONDS).toOffsetDateTime().toString()
)。如果您需要,通过格式模式字符串构建自己的格式化程序非常灵活。但是,我们经常可以用更少的时间(然后应该为我们的代码更容易维护)来实现:toString
方法或内置格式化程序,包括ISO和我们可以从{获得的本地化格式化程序{1}}。
这是什么" T"是指BTW?
DateTimeFormatter.ofLocalizedPattern()
是ISO 8601格式的一部分。它将日期部分与时间部分分开。您可以将其视为时间T,因为它表示时间部分的开始。如果只有一个日期(T
)或仅一个时间段(2018-04-25
),则不会使用21:45:00
,但如果我们同时使用T
,则T
} 是必须的。您可能认为可能在没有T
的情况下指定了格式,您可能是对的。但是,当涉及到期间/持续时间的格式时,它是必不可少的,并且在没有日期时也需要:P3M
表示3个月的期间,而PT3M
表示3分钟。
链接:在Wikipedia article on ISO 8601中阅读更多内容。