79175815

Date: 2024-11-10 21:11:04
Score: 0.5
Natty:
Report link

java.time

Today it‘s recommended that you use java.time, the modern Java date and time API, for your time work. Avoid Date and SimpleDateFormat since they had bad design problems (of which you have only seen a little bit) and have been outdated since Java 8, which came out more than 10 years ago.

The correct way to do your conversion depends on whether your string in mm ss.S format denotes an amount of time or a time of day since these concepts are represented by different java.time classes. You would confuse your reader if you used the wrong one.

Converting an amount of time

Since your string does not include any hours, I considered an amount of time up to one hour more likely. For that we need the Duration class. Duration isn‘t very well suited for parsing, so we have a little hand work to do:

    String amountOfTimeString = " 14 37 485";
    String[] parts = amountOfTimeString.trim().split(" ");
    Duration duration = Duration.ofMinutes(Integer.parseInt(parts[0]))
            .plusSeconds(Integer.parseInt(parts[1]))
            .plusMillis(Integer.parseInt(parts[2]));
    System.out.println("Duration: " + duration);
    double seconds = duration.toSeconds() + duration.getNano() / NANOS_PER_SECOND;
    System.out.println("Seconds: " + seconds);

Output from this snippet is:

Duration: PT14M37.485S
Seconds: 877.485

So 877.485 seconds, a positive number as expected. If you like, you may use the first line of output to verify that parsing is correct: PT14M37.485S means 14 minutes 37.485 seconds, which agrees with the input string of 14 37 485.

Converting a time of day

For a time of day we need the LocalTime class. It can parse your string with the help of a DateTimeFormatter. So declare:

private static final DateTimeFormatter TIME_PARSER
        = new DateTimeFormatterBuilder()
                .appendPattern(" mm ss ")
                .appendValue(ChronoField.MILLI_OF_SECOND)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .toFormatter(Locale.ROOT);

public static final double NANOS_PER_SECOND = Duration.ofSeconds(1).toNanos();

Then do:

    String timeOfDayString = " 14 37 485";
    LocalTime time = LocalTime.parse(timeOfDayString, TIME_PARSER);
    System.out.println("Time of day: " + time);

    int wholeSeconds = time.get(ChronoField.SECOND_OF_DAY);
    int nanoOfSecond = time.getNano();

    double secondOfDay = wholeSeconds + (nanoOfSecond / NANOS_PER_SECOND);
    System.out.println("secondOfDay: " + secondOfDay);

Output agrees with the output from before:

Time of day: 00:14:37.485
secondOfDay: 877.485

What went wrong in your code?

Why is it negative?

Is there something wrong with the code?

We don‘t really need to know since we are not using Date and SimpleDateFormat any more -- fortunately! But out of curiosity.

First, the Date class that you tried to use never was able to represent an amount of time. And it could represent a time of day only if you assumed a date and a time zone.

To give a full account of what I think happened in your code I have made some assumptions, but even if the concrete assumptions are not to the point, I still believe that the idea in my explanation is. I assume that you were running your code in a Central European time zone such as Europe/Oslo or Europe/Rome or some other time zone that used UTC offset +01:00 in February 2013. Next I assume you ran your code at 13:14:37.485 before posting your question at 13:44 in your time zone. Or at some other hour where the minutes and seconds were 14:37.485.

Then this happens: new Date() produces a Dateobject representing the current point in time. This is formatted into a String of 14 37 485. This string is parsed back into a Date of Thu Jan 01 00:14:37 CET 1970 because defaults of 1970-01-01 and your default time zone are confusingly applied. The getTime method returns the number of milliseconds since the start of 1070-01-01 in UTC, the so-called epoch. Because of your UTC offset of +01:00, in UTC the date and time mentioned are equal to 1969-12-31T23:14:37.485Z, so before the epoch. This explains why a negative number comes out. Your observed rsult of -2722.515 corresponds to 45 minutes 22.515 seconds before the epoch, so the time I just mentioned.

Link

Oracle Tutorial trail: Date Time explaining how to use java.time.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Unregistered user (0.5):
  • Low reputation (1):
Posted by: Onalerona Gruber