Java: DateTimeFormatter在秒和毫秒全为0时解析时间字符串失败?
Java: DateTimeFormatter fail to parse time string when seconds and milliseconds are all 0s?
基本上,我使用以下代码将字符串解析为 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。
我不确定为什么它不起作用,这似乎是一个 bug 因为 当我使用 :
20180301091600001 result is 2018-03-01T09:16:00.001
----------------^ -----------------^^^^^^
还有一个测试:
2018030100000000 result is 2018-03-01T00:00
--------^^^----- -----------^^^^^^^^^^^
似乎解析器忽略了seconds和millisecond当它为零时,为什么?
为什么? 的完整解释在 的答案中。
解决方案
这里有一个快速修复方法,您可以使用像这样的另一个格式化程序:
var result = LocalDateTime.parse("20180301091600000", dtformatter)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS"));
输出
2018-03-01T09:16:00:000
tl;博士
where the seconds and millseconds are 00000 and this is when the parser fails
否,解析器成功。您的问题是 生成 字符串,而不是解析。
默认 DateTimeFormatter
以秒和小数秒为单位抑制零值,as documented。
功能,不是错误
您的问题不在于解析,而在于在 解析之后生成字符串。请记住,日期时间对象的文本表示与对象不同且分离。换句话说,日期时间对象没有“格式”。
[String] --> parse
--> [LocalDateTime] --> toString
--> [String]
LocalDateTime::toString
的文档明确指出,当在最不重要的部分遇到零值时,将使用尽可能短的格式变化。引用:
The output will be one of the following ISO-8601 formats:
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
The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.
例子
关于 中显示的两个示例…
20180301091600001 result is 2018-03-01T09:16:00.001
在该示例中,最低有效部分(毫秒)具有非零值,因此它在结果中表示。
2018030100000000 result is 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
问题问:
How can I fix it to make it print 2018-03-01T09:16:00.000 instead of 2018-03-01T09:16 ?
指定自定义格式化程序而不是默认格式化程序。
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS") ;
String output = ldt.format( f ) ;
但请记住,您生成的字符串将禁止在 LocalDateTime
对象中显示任何微秒或纳秒。
基本上,我使用以下代码将字符串解析为 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。
我不确定为什么它不起作用,这似乎是一个 bug 因为 当我使用 :
20180301091600001 result is 2018-03-01T09:16:00.001
----------------^ -----------------^^^^^^
还有一个测试:
2018030100000000 result is 2018-03-01T00:00
--------^^^----- -----------^^^^^^^^^^^
似乎解析器忽略了seconds和millisecond当它为零时,为什么?
为什么? 的完整解释在
解决方案
这里有一个快速修复方法,您可以使用像这样的另一个格式化程序:
var result = LocalDateTime.parse("20180301091600000", dtformatter)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS"));
输出
2018-03-01T09:16:00:000
tl;博士
where the seconds and millseconds are 00000 and this is when the parser fails
否,解析器成功。您的问题是 生成 字符串,而不是解析。
默认 DateTimeFormatter
以秒和小数秒为单位抑制零值,as documented。
功能,不是错误
您的问题不在于解析,而在于在 解析之后生成字符串。请记住,日期时间对象的文本表示与对象不同且分离。换句话说,日期时间对象没有“格式”。
[String] -->
parse
--> [LocalDateTime] -->toString
--> [String]
LocalDateTime::toString
的文档明确指出,当在最不重要的部分遇到零值时,将使用尽可能短的格式变化。引用:
The output will be one of the following ISO-8601 formats:
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
The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.
例子
关于
20180301091600001 result is 2018-03-01T09:16:00.001
在该示例中,最低有效部分(毫秒)具有非零值,因此它在结果中表示。
2018030100000000 result is 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
问题问:
How can I fix it to make it print 2018-03-01T09:16:00.000 instead of 2018-03-01T09:16 ?
指定自定义格式化程序而不是默认格式化程序。
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS") ;
String output = ldt.format( f ) ;
但请记住,您生成的字符串将禁止在 LocalDateTime
对象中显示任何微秒或纳秒。