Format java.time.Duration for String

Asked

Viewed 547 times

3

The code below is producing the following output:

Resultado: PT2H30M

I wish it were:

Resultado: 2:30

Does anyone know how I can do?

import java.time.Duration;
import java.time.LocalDateTime;

public class TesteDuration {
public static void main(String[] args) {

    LocalDateTime primeiraData = LocalDateTime.of(2017, Month.JANUARY, 10, 14, 00, 00);
    LocalDateTime segundaDate = LocalDateTime.of(2016, Month.JANUARY, 10, 16, 30, 00);

    Duration testeDuration = Duration.between(primeiraData, segundaDate);
    System.out.println("Resultado: " + testeDuration.toString());

}
  • This code does not give this result.

2 answers

4

Following this answer withdrawal of Soen, you can use String.format:

LocalDateTime primeiraData = LocalDateTime.of(2017, Month.JANUARY, 10, 14, 00, 00);
LocalDateTime segundaDate = LocalDateTime.of(2017, Month.JANUARY, 10, 16, 30, 00);

Duration testeDuration = Duration.between(primeiraData, segundaDate);
long s = testeDuration.getSeconds();
System.out.println("Resultado: " + String.format("%d:%02d", s / 3600, (s % 3600) / 60));

See working on IDEONE.

Remembering that in your code, you are comparing a time period of different dates and the best to make this kind of comparison is the class Period. For comparisons of the same date, the above code works perfectly.

  • Resolved... thank you very much.

3


Another way of doing, complementing the response of diegofm, is you go subtracting the date fields one by one to remove from it, each component.

For example:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;

class TesteDurationNovo {
    public static void main(String[] args) {

        LocalDateTime primeiraData = LocalDateTime.of(2017, Month.JANUARY, 10, 14, 00, 00);
        LocalDateTime segundaDate = LocalDateTime.of(2016, Month.JANUARY, 10, 16, 30, 00);

        Duration testeDuration = Duration.between(primeiraData, segundaDate);
        long dias = testeDuration.toDays();
        Duration d2 = testeDuration.minus(dias, ChronoUnit.DAYS);
        long horas = d2.toHours();
        Duration d3 = d2.minus(horas, ChronoUnit.HOURS);
        long minutos = d3.toMinutes();
        Duration d4 = d3.minus(minutos, ChronoUnit.MINUTES);
        long segundos = d4.getSeconds();
        Duration d5 = d4.minus(segundos, ChronoUnit.SECONDS);
        long nanos = d5.toNanos();
        Duration d6 = d5.minus(nanos, ChronoUnit.NANOS);

        System.out.println("Total: " + dias + " dias, " + horas + " horas, " + minutos + " minutos, " + segundos + " segundos, " + nanos + " ns.");
        System.out.println("Resultado: " + testeDuration.toString());
        if (!d6.isZero()) throw new AssertionError(d6.toString());
    }
}

Here’s the way out:

Total: -365 dias, -21 horas, -30 minutos, 0 segundos, 0 ns.
Resultado: PT-8781H-30M

This means that your period is 365 days, 21 hours and 30 minutes negative. The period is negative because the primeiraData is after the segundaDate. This can be arranged if you simply change the dates you assign to each variable, or if you change the order of the parameters in the method between(Temporal, Temporal), or even if you call the method abs() of Duration and only then store the result in the variable testeDuration.

It is not possible to subtract months or years in a simple and direct way from the Duration because not every month and not every year have the same size. That’s why there are no methods toMonths() or toYears().

As to the outcome of toString(), that PT-8781H-30M means only that the duration is -8781 hours and -30 minutes. A String returned will always contain the amount of hours, minutes and seconds of the Duration, may be the number of fractional seconds for cases including nanoseconds and the number of hours for all practical purposes unlimited.

Already that if at the end is just to make sure that the Duration remaining after subtracting all fields is zero. If it were not, it would be because something wrong was happening in the above process, a fact that would then be denounced by the release of a AssertionError.

See here working on ideone.

Ah, and if you change the primeiraData for 2016 instead of 2017, you will get this result:

Total: 0 dias, 2 horas, 30 minutos, 0 segundos, 0 ns.
Resultado: PT2H30M

I believe that’s what you had when you got it PT2H30M as an exit.

And if you are sure that your result will only be in hours and minutes, you could do that, similar to diegofm’s response:

System.out.println("Resultado: " + String.format("%d:%02d", horas, minutos));

However, this will not work if you have to consider hours, days, seconds or nanoseconds as well. It won’t work either if the period is negative. Therefore, you should look for what will work best for you considering the dates and periods your program will have to deal with.

  • Resolved... thank you very much.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.