How to subtract hours in java?

Asked

Viewed 1,981 times

3

I am trying to days make the difference of hours in my application. The case is as follows: Based on the Current time and current minute, I want to compare another time I have in a string and I need to know how many hours and how many minutes remain, even if the other time string is the next day.

String time must have the following format:

String horario = "07:30";

I tried the following code but was unsuccessful:

     Calendar hoje = Calendar.getInstance();
        String minutosAtual = 
        String.valueOf(hoje.get(Calendar.MINUTE));
        calendar = new GregorianCalendar();
        String strinHora = "14:20";
        String[] hora = strinHora.split(":");
        Integer.parseInt(hora[0]));
        calendar.get(Calendar.MINUTE));
        int minutoInt = calendar.get(Calendar.MINUTE);

        calendar.add(Calendar.HOUR, -Integer.parseInt(hora[0]));
        calendar.add(Calendar.MINUTE, -Integer.parseInt(hora[1]));

        //Define Format of date
        SimpleDateFormat dataFormatada = new 
        SimpleDateFormat("HH:mm");
        String dateStrin = dataFormatada.format(calendar.getTime());
        System.out.println(dateStrin);

Can someone help me?

2 answers

4


If you can/want to use the java.time, see my another answer.

But without using the java.time, can do this by creating a class Horario. That class Horario is a twig-breaker that fits when you don’t have the class java.time.LocalTime available:

import java.util.Calendar;
import java.util.GregorianCalendar;

class Teste {

    private static void mostrar(Horario agora, String objetivo) {
        Horario desejada = Horario.parse(objetivo);
        Horario falta = desejada.diferenca(agora);
        System.out.println(
                "Entre " + agora
                + " e " + desejada
                + ", a diferença é de " + falta
                + ".");
    }

    public static void main(String[] args) {
        Horario agora = Horario.agora();
        mostrar(agora, "07:30");
        mostrar(new Horario( 5, 30), "07:30");
        mostrar(new Horario( 7, 10), "07:30");
        mostrar(new Horario( 0,  0), "07:30");
        mostrar(new Horario( 7,  0), "07:30");
        mostrar(new Horario( 7, 30), "07:30");
        mostrar(new Horario( 7, 31), "07:30");
        mostrar(new Horario(10,  0), "07:30");
        mostrar(new Horario(19, 30), "07:30");
        mostrar(new Horario(23, 59), "07:30");
        mostrar(new Horario( 0,  0), "23:59");
        mostrar(new Horario(23, 59), "00:00");
    }
}

class Horario {
    private final int horas;
    private final int minutos;

    public Horario(int horas, int minutos) {
        if (horas < 0 || horas > 23 || minutos < 0 || minutos > 59) {
            throw new IllegalArgumentException();
        }
        this.horas = horas;
        this.minutos = minutos;
    }

    public int getHoras() {
        return horas;
    }

    public int getMinutos() {
        return minutos;
    }

    public static Horario parse(String input) {
        char[] cs = input.toCharArray();
        if (cs.length != 5) throw new IllegalArgumentException();
        for (int i = 0; i < 5; i++) {
            if (i == 2) continue;
            if (cs[i] < '0' || cs[i] > '9') throw new IllegalArgumentException();
        }
        if (cs[2] != ':') throw new IllegalArgumentException();

        int h = (cs[0] - '0') * 10 + cs[1] - '0';
        int m = (cs[3] - '0') * 10 + cs[4] - '0';
        return new Horario(h, m);
    }

    public static Horario agora() {
        GregorianCalendar gc = new GregorianCalendar();
        return new Horario(gc.get(Calendar.HOUR_OF_DAY), gc.get(Calendar.MINUTE));
    }

    public Horario diferenca(Horario outro) {
        int difHoras = this.horas - outro.horas;
        int difMinutos = this.minutos - outro.minutos;
        while (difMinutos < 0) {
            difMinutos += 60;
            difHoras--;
        }
        while (difHoras < 0) {
            difHoras += 24;
        }
        return new Horario(difHoras, difMinutos);
    }

    @Override
    public String toString() {
        return ((horas < 10) ? "0" : "") + horas + ":" + ((minutos < 10) ? "0" : "") + minutos;
    }
}

The class Horario implements the logic of the time you want. The GregorianCalendar is used only to pick up the time of the clock and nothing else. After all, work with the GregorianCalendar is something torturous (and therefore I try to minimize its use). Besides, there is in the package java.util no class representing times without dates.

Here is the output produced:

Entre 06:27 e 07:30, a diferença é de 01:03.
Entre 05:30 e 07:30, a diferença é de 02:00.
Entre 07:10 e 07:30, a diferença é de 00:20.
Entre 00:00 e 07:30, a diferença é de 07:30.
Entre 07:00 e 07:30, a diferença é de 00:30.
Entre 07:30 e 07:30, a diferença é de 00:00.
Entre 07:31 e 07:30, a diferença é de 23:59.
Entre 10:00 e 07:30, a diferença é de 21:30.
Entre 19:30 e 07:30, a diferença é de 12:00.
Entre 23:59 e 07:30, a diferença é de 07:31.
Entre 00:00 e 23:59, a diferença é de 23:59.
Entre 23:59 e 00:00, a diferença é de 00:01.

See here working on ideone.

  • 1

    That class Horario is simply fantastic. I found it very interesting you implement the conversions along with comparisons too :)

  • Dude, it worked great and this class is fantastic!!! I only had to change one detail: gc.get(Calendar.HOUR for gc.get(Calendar.HOUR_OF_DAY. Congratulations @Victor Satafusa and thank you very much!!

  • @Edeson.A.Bizerril Well noted! I’ve already edited the answer to tidy up this detail. I’ve also added the methods getHoras() and getMinutos() that you had forgotten and that you will probably need after.

  • Thanks! You are 10!

3

Use the class java.time.LocalTime. See more about her in this other question and answer my.

If you want to do it without using the package java.time, see my other answer to this question.

Here is an example code:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;

class TesteDatas {
    private static final DateTimeFormatter FORMATO_HORAS = DateTimeFormatter
            .ofPattern("HH:mm")
            .withResolverStyle(ResolverStyle.STRICT);

    private static LocalTime faltando(LocalTime agora, LocalTime desejada) {
        return desejada.minusHours(agora.getHour()).minusMinutes(agora.getMinute());
    }

    private static void mostrar(LocalTime horario, String objetivo) {
        LocalTime desejada = LocalTime.parse(objetivo, FORMATO_HORAS);
        LocalTime falta = faltando(horario, desejada);
        System.out.println(
                "Entre " + horario.format(FORMATO_HORAS)
                + " e " + desejada.format(FORMATO_HORAS)
                + ", a diferença é de " + falta.format(FORMATO_HORAS)
                + ".");
    }

    public static void main(String[] args) {
        LocalTime agora = LocalTime.now();
        mostrar(agora, "07:30");
        mostrar(LocalTime.of( 5, 30), "07:30");
        mostrar(LocalTime.of( 7, 10), "07:30");
        mostrar(LocalTime.of( 0,  0), "07:30");
        mostrar(LocalTime.of( 7,  0), "07:30");
        mostrar(LocalTime.of( 7, 30), "07:30");
        mostrar(LocalTime.of( 7, 31), "07:30");
        mostrar(LocalTime.of(10,  0), "07:30");
        mostrar(LocalTime.of(19, 30), "07:30");
        mostrar(LocalTime.of(23, 59), "07:30");
        mostrar(LocalTime.of( 0,  0), "23:59");
        mostrar(LocalTime.of(23, 59), "00:00");
    }
}

Here is the output (the first line will vary according to the time you run):

Entre 01:02 e 07:30, a diferença é de 06:28.
Entre 05:30 e 07:30, a diferença é de 02:00.
Entre 07:10 e 07:30, a diferença é de 00:20.
Entre 00:00 e 07:30, a diferença é de 07:30.
Entre 07:00 e 07:30, a diferença é de 00:30.
Entre 07:30 e 07:30, a diferença é de 00:00.
Entre 07:31 e 07:30, a diferença é de 23:59.
Entre 10:00 e 07:30, a diferença é de 21:30.
Entre 19:30 e 07:30, a diferença é de 12:00.
Entre 23:59 e 07:30, a diferença é de 07:31.
Entre 00:00 e 23:59, a diferença é de 23:59.
Entre 23:59 e 00:00, a diferença é de 00:01.

The key to calculating the difference is in the method faltando:

    private static LocalTime faltando(LocalTime agora, LocalTime desejada) {
        return desejada.minusHours(agora.getHour()).minusMinutes(agora.getMinute());
    }

That is, to calculate the difference between the two times, the hours and minutes are subtracted. The class LocalTime turns around midnight in case of times that would be negative or that would exceed 23:59.

See here working on ideone.

Ah, it’s important to remember that objects like java.time.format.DateTimeFormatter only need to be created once and can be reused at will. They are thread-safe and immutable and you can put them into static variables. This is something that does not occur with the java.util.SimpleDateFormatter.

  • But in the android API, depending on which one it’s using, there’s still no support for java-8. OP would probably have to import the lib from jodatime. See: https://stackoverflow.com/a/36028494/5524514

  • I think there is some problem, because the imports not working in Android Studio. Use linux, Open JDK, is that the problem? Do you have a solution to solve, like a dependency? Grateful!

  • @Edeson.A.Bizerril This depends on Java 8. What is the version of your android?

  • @Edeson.A.Bizerrilv adds the android API What will work, it already supports full java-8.

  • @Article See this: https://developer.android.com/reference/java/time/package-summary.html - This is supported with API level 26. However, this is not yet very popularized.

  • @Victorstafusa yes, I commented after searching here, but this api is still new, the feature will probably only work on models with android O, which has not even left the testing phase yet. Perhaps it would be interesting an alternative to work on the N api as well.

  • @Articuno I posted another answer without using the java.time (and Edeson must be notified of it, of course).

  • 1

    @Carlosheuberger Only with schedules you can’t do that. In this case you would need to have the date too. After all, looking at a string "07:30" and to another "07:30" can’t tell if they’re on the same day or not if you don’t have that information coming from somewhere else.

  • Guys, thank you so much for your comments. When I said, "even if the other time string is the next day", I am referring in the case similar to this: "Between 00:00 and 23:59, the difference is 23:59", quoted in the first example. Note that in this example, we have almost 24 hours from one hour to the next. In my case, I will not have such extreme situations. I actually have a vector that the last time is 6:30 and the first time is 7:30 the next day.

Show 4 more comments

Browser other questions tagged

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