3

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Nitishkumar Singh
  • 1,781
  • 1
  • 15
  • 33
  • 1
    A `LocalTime` is for time of day, is this what you intend? 10.337 seconds past midnight? If, on the other hand, you’ve got a duration, an amount of time, the `Duration` class is the right one to use. – Ole V.V. Nov 26 '17 at 08:48
  • 2
    I think you mean 10 seconds and 337000 *microseconds*? There are 1,000,000,000 nanoseconds in a second, so they would usually be written with 9 decimals – Ole V.V. Nov 26 '17 at 11:06

1 Answers1

3

There are a couple of options.

If your time string denotes an amount of time

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

If your time string denotes a time of day

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161