I am trying to parse second and nanosecond, i.e., 10.337000, where 10 is second and 337000 is nanoseconds in Java 8. I am not able to figure out how should I parse these values into LocalTime
.
I have tried DateTimeFormatter.ofPattern("ss:nnnnnn")
, but it didn't work.
There are a couple of options.
For a duration, an amount of time (in days, hours, minutes, seconds and/or fraction of second) the Duration
class in java.time
is the right one to use:
String timeString = "10.337000";
Duration amountOfTime = Duration.parse("PT" + timeString + "S");
System.out.println("Duration: " + amountOfTime);
System.out.println("Seconds: " + amountOfTime.getSeconds());
System.out.println("Nanos: " + amountOfTime.getNano());
This prints
Duration: PT10.337S
Seconds: 10
Nanos: 337000000
We got 337000000 nanoseconds. I assume this is correct since there are 1,000,000,000 nanoseconds in a second (a millionth of a second is called a microsecond).
The Duration
class has limited parsing and formatting capabilities. It parses ISO 8601 format, which goes like PT10.337000S
, so I just put the correct letters in front of and at the end of your string, and it worked. You see the Duration.toString()
also prints the same format back (omitting superfluous 0 decimals).
You asked for a LocalTime
. A LocalTime
is for hour of day, so if you intended 10.337 seconds past midnight, this is the correct class to use. One easy option is to prepend a string to match ISO 8601 format for a time without an offset from UTC, similarly to what I did for the duration:
LocalTime time = LocalTime.parse("00:00:" + timeString);
This gives a LocalTime
of
00:00:10.337
Again, toString()
just gives as many groups of three decimals as necessary to render the full precision.
You mentioned using a DateTimeFormatter
, and you may want to stick to this idea. This will allow you to build your formatter once in one place and use it in other places in your code without having to worry about prepending a string. We need to tell the formatter to set the minutes and hours to 0, and in order to do that, we need to go through a DateTimeFormatterBuilder
:
DateTimeFormatter timeParser = new DateTimeFormatterBuilder()
.appendPattern("s.SSSSSS")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.toFormatter();
LocalTime time = LocalTime.parse(timeString, timeParser);
This gives exactly the same result as before, a LocalTime
of 00:00:10.337.
The formatter in this snippet requires exactly 6 decimals on the seconds (since there are 6 capital S
after the decimal point). If your number of decimals may vary, you need to look into the DateTimeFormatterBuilder.appendFraction
method.