tl;dr
where the seconds and millseconds are 00000 and this is when the parser fails
No, the parser succeeds. Your issue is with generating a String, not parsing.
The default DateTimeFormatter
suppresses zero values in seconds and fractional second, as documented.
Feature, not a bug
Your problem is not in the parsing, but in the generating of a string after parsing. Keep in mind that the textual representation of a date-time object is distinct and separate from the object. In other words, a date-time object does not have a “format”.
[String] --> parse
--> [LocalDateTime] --> toString
--> [String]
The documentation for LocalDateTime::toString
clearly says that the shortest possible formatting variation will be used when encountering zero values in the least-significant parts. To quote:
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.
Examples
Regarding two examples shown in the accepted Answer by YCF_L…
20180301091600001 result is 2018-03-01T09:16:00.001
In that example, the least-significant part (millisecond) has a non-zero value, so it is represented in the result.
2018030100000000 result is 2018-03-01T00:00
In that example, the least significant parts of hour, minute, second, milliseconds, microseconds, and nanoseconds are all zero. So their display is suppressed, except for hours and minutes as the documentation promises that year-minute is always displayed.
So both of your examples work as documented; feature, not a bug.
Solution
The solution is to not use the default formatter provided in the toString
method. Instead, use another formatter. For example, use the same custom formatter you defined for parsing.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS" );
LocalDateTime ldt = LocalDateTime.parse( "20180301091600000" , f );
String outputDefault = ldt.toString();
String outputCustom = ldt.format( f );
Dump to console.
System.out.println( "outputDefault: " + outputDefault );
System.out.println( "outputCustom: " + outputCustom );
outputDefault: 2018-03-01T09:16
outputCustom: 20180301091600000
The Question asks:
How can I fix it to make it print 2018-03-01T09:16:00.000 instead of 2018-03-01T09:16 ?
Specify a custom formatter instead of the default formatter.
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS") ;
String output = ldt.format( f ) ;
But keep in mind your generated String will suppress display of any microseconds or nanoseconds in the LocalDateTime
object.
LocalDateTime
. You should format your print as well. – Alamo2018-03-01T09:16
– Teacake2018-03-01T09:16:00.000
is ISO 8601, but so is2018-03-01T09:16
, so any API that accepts the former, I would expect it to accept the latter too. Try and see if you’re not all fine. – Crib20180301091600001
return2018-03-01T09:16:00.001
but20180301091600000
return2018-03-01T00:00
why its not return2018-03-01T00:00:00.000
– Teacake2018-03-01T00:00
it’s understood that the seconds and fraction of seconds are 0, so printing them is not needed. I think Basil Bourque’s answer explains. BTW and for comparison, if you wanted to print the full precision of theLocalDateTime
object, you would need2018-03-01T00:00:00.000000000
. – CribLocalDateTime
object doesn’t know (doesn’t remember) which string it was parsed from. It just holds a date and a time of day (with nanoseconds precision). – Crib2018-03-01T09:16:00.000
instead of2018-03-01T09:16
so I think my solution is correct no? – Teacake