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

时间:2018-04-22 14:40:39

标签: java date format java-time java-10

基本上,我使用以下代码将字符串解析为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。

2 个答案:

答案 0 :(得分:4)

TL;博士

  

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

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

默认DateTimeFormatter以秒为单位抑制零值,小时秒{@ 3}}。

功能,而不是错误

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

  

[String] - > parse - > [LocalDateTime] - > toString - > [字符串]

as documented的文档清楚地表明,在最不重要的部分遇到零值时,将使用最短的格式变化。引用:

  

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

     

UUUU-MM-dd'T'HH:毫米

     

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

     

使用的格式是最短的,输出省略的部分隐含为零的时间的全部值。

实施例

关于LocalDateTime::toString ...

中显示的两个例子
  

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

outputDefault:2018-03-01T09:16

     

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

但请记住,生成的String会抑制LocalDateTime对象中任何微秒或纳秒的显示。

答案 1 :(得分:3)

我不确定为什么它不起作用,它似乎是 bug ,因为当我使用时:

this

另一个测试:

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

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

完整的解释为什么?,是Basil Bourque的答案。

解决方案

这是一个快速修复,你可以使用另一个格式化程序:

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

<强>输出

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