Java:当秒和毫秒均为 0 时,DateTimeFormatter 无法解析时间字符串?

问题描述 投票:0回答:3

基本上,我使用以下代码将字符串解析为 LocalDateTime,大多数情况下都可以正常工作。

DateTimeFormatter dtformatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");

但是,我遇到了秒和毫秒为

00000
的情况,此时解析器失败并打印
LocalDateTime
2018-03-01T09:16
而不是
2018-03-01T09:16:00.000

System.out.println(LocalDateTime.parse("20180301091600000",dtformatter));

(请注意,在我的代码中,我必须将字符串解析为

LocalDateTime
,进行一些比较,然后在最后将
LocalDateTime
打印到 csv)

如何修复它以使其打印

2018-03-01T09:16:00.000
而不是
2018-03-01T09:16

仅供参考,我使用的是jdk10。

java date format java-time java-10
3个回答
5
投票

我不知道为什么它不起作用,它似乎是一个bug因为当我使用时:

20180301091600001        result is      2018-03-01T09:16:00.001
----------------^                       -----------------^^^^^^

还有另一个测试:

2018030100000000         result is      2018-03-01T00:00
--------^^^-----                        -----------^^^^^^^^^^^

当它为零时,解析器似乎忽略了毫秒,为什么?

完整的解释为什么?,在Basil Bourque的回答中。


解决方案

这是一个快速修复,您可以使用另一个格式化程序,如下所示:

var result = LocalDateTime.parse("20180301091600000", dtformatter)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS"));

输出

2018-03-01T09:16:00:000

5
投票

tl;博士

其中秒和毫秒为 00000,这是解析器失败的时候

不,解析器成功。您的问题是生成字符串,而不是解析。

默认值

DateTimeFormatter
抑制以秒为单位的零值和小数秒,如文档所述

功能,而不是错误

您的问题不在于解析,而在于解析后生成字符串。请记住,日期时间对象的文本表示是不同的,并且与该对象是分开的。换句话说,日期时间对象没有“格式”。

[字符串] -->

parse

 --> [本地日期时间] --> 
toString
 --> [字符串]

LocalDateTime::toString

的文档明确指出,当在最低有效部分遇到零值时,将使用尽可能短的格式变化。引用:

输出将是以下 ISO-8601 格式之一:

uuuu-MM-dd'T'HH:mm

uuuu-MM-dd'T'HH:mm:ss

uuuu-MM-dd'T'HH:mm:ss.SSS

uuuu-MM-dd'T'HH:mm:ss.SSSSSS

uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS

使用的格式将是输出时间的完整值的最短格式,其中省略的部分隐含为零。

示例

关于

YCF_L接受的答案中显示的两个示例…

20180301091600001 结果是 2018-03-01T09:16:00.001

在该示例中,最低有效部分(毫秒)具有非零值,因此它会在结果中表示。

2018030100000000 结果是 2018-03-01T00:00

在该示例中,小时、分钟、秒、毫秒、微秒和纳秒的最低有效部分均为零。因此,除了小时和分钟之外,它们的显示被抑制,因为文档承诺始终显示年-分钟。

因此,您的两个示例都按记录工作;功能,而不是错误。

解决方案

解决方案是不使用

toString

 方法中提供的默认格式化程序。相反,请使用其他格式化程序。例如,使用您为解析定义的相同自定义格式化程序。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS" ); LocalDateTime ldt = LocalDateTime.parse( "20180301091600000" , f ); String outputDefault = ldt.toString(); String outputCustom = ldt.format( f );

转储到控制台。

System.out.println( "outputDefault: " + outputDefault ); System.out.println( "outputCustom: " + outputCustom );

输出默认:2018-03-01T09:16

输出自定义:20180301091600000

问题问:

如何修复它以使其打印 2018-03-01T09:16:00.000 而不是 2018-03-01T09:16 ?

指定自定义格式化程序而不是默认格式化程序。

DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS") ; String output = ldt.format( f ) ;

但请记住,生成的字符串将抑制

LocalDateTime

 对象中任何微秒或纳秒的显示。


0
投票
@BasilBourque 我对上面的回答有进一步的疑问 当我们在 OffsetDateTime 中解析此日期时,我有一个日期“2023-12-10T00:00:00.000” 解析的 OffsetDateTime 对象永远不会有秒和纳秒。我们可以以某种方式将秒和纳秒添加到 OffsetDateTime 对象中吗? 请参阅随附的代码片段和调试信息

private fun parse3(date:String) { val ldt: LocalDateTime = LocalDateTime.parse("2023-12-10T00:00:00.000", df) val odt = OffsetDateTime.of(ldt, ZoneOffset.of("+07:00")) val outputDefault = odt.toString() val outputCustom = odt.format(df) println( "outputDefault: " + outputDefault) println( "outputCustom: " + outputCustom) }

© www.soinside.com 2019 - 2024. All rights reserved.