1. Adição e subtração de datas e horas
No desenvolvimento, trabalhar com datas e horas — não é apenas “mostrar a data na tela”. Muitas vezes é preciso:
- saber quantos dias faltam para um evento importante;
- calcular a idade do usuário;
- determinar quanto tempo se passou entre dois eventos;
- verificar se o deadline já chegou;
- adicionar à data uma quantidade de dias, semanas, meses ou horas.
Por exemplo, no nosso aplicativo queremos lembrar ao usuário que faltam 3 dias para o deadline da tarefa. Ou parabenizá-lo pelo aniversário que já passou (se a data já ficou no passado).
Para isso, em java.time há classes e métodos especiais que tornam esses cálculos simples e seguros.
Métodos básicos para somar e subtrair
Todos os tipos de data e hora (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant) têm métodos:
- plusXxx() — adicionar (dias, meses, anos, horas, minutos etc.)
- minusXxx() — subtrair (idem)
import java.time.LocalDate;
LocalDate today = LocalDate.now(); // Data de hoje
LocalDate tomorrow = today.plusDays(1); // Amanhã
LocalDate nextMonth = today.plusMonths(1); // Daqui a um mês
LocalDate lastWeek = today.minusWeeks(1); // Uma semana atrás
System.out.println("Hoje: " + today);
System.out.println("Amanhã: " + tomorrow);
System.out.println("Daqui a um mês: " + nextMonth);
System.out.println("Uma semana atrás: " + lastWeek);
Todos esses métodos retornam um novo objeto, não alteram o original. Imutabilidade é tudo!
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime inTwoHours = now.plusHours(2);
LocalTime tenMinutesAgo = now.minusMinutes(10);
System.out.println("Agora: " + now);
System.out.println("Daqui a 2 horas: " + inTwoHours);
System.out.println("Há 10 minutos: " + tenMinutesAgo);
Métodos combinados
LocalDate vacation = today.plusMonths(2).plusDays(10);
System.out.println("Férias: " + vacation);
2. Obtendo a diferença entre datas: Period e Duration
Quando precisamos saber quanto tempo passou entre duas datas ou instantes, entram em cena dois protagonistas — Period e Duration. Vamos conhecê-los melhor.
Qual é a diferença entre Period e Duration?
- Period — para trabalhar com datas (ano, mês, dia). Ex.: “3 anos, 2 meses e 5 dias”.
- Duration — para trabalhar com tempo (horas, minutos, segundos, nanossegundos). Ex.: “5 horas e 30 minutos”.
| Classe | Para que serve | Exemplo de uso |
|---|---|---|
|
Diferença entre datas | Quantos anos/meses/dias entre datas |
|
Diferença entre instantes | Quantas horas/minutos/segundos entre eventos |
Exemplo: calculando a idade do usuário
import java.time.LocalDate;
import java.time.Period;
LocalDate birthday = LocalDate.of(2000, 1, 15); // Data de nascimento
LocalDate today = LocalDate.now();
Period age = Period.between(birthday, today);
System.out.println("Idade: " + age.getYears() + " anos, " +
age.getMonths() + " meses, " +
age.getDays() + " dias");
Analogia: Period é como uma diferença “humana” entre datas (“tenho 24 anos 5 meses e 12 dias”).
Exemplo: quanto tempo falta para o deadline
import java.time.LocalDate;
LocalDate deadline = LocalDate.of(2025, 7, 1);
LocalDate today = LocalDate.now();
if (today.isBefore(deadline)) {
Period left = Period.between(today, deadline);
System.out.println("Até o deadline faltam: " +
left.getMonths() + " meses e " +
left.getDays() + " dias");
} else {
System.out.println("O deadline já passou!");
}
Duration: diferença no tempo
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
Duration duration = Duration.between(start, end);
System.out.println("Duração: " + duration.toHours() + " horas " +
(duration.toMinutes() % 60) + " minutos");
Duration mede a diferença em segundos, minutos, horas, dias (mas dias — sempre de 24 horas, sem considerar peculiaridades do calendário).
Comparação: quando usar Period e quando usar Duration?
- Se você tem apenas datas (sem horário), use Period.
- Se você tem horário (por exemplo, LocalDateTime, Instant), use Duration.
3. Comparando datas e horas: isBefore, isAfter, equals
Às vezes só precisamos entender: a data já chegou ou ainda não? O evento está no passado ou no futuro? Para isso, todos os tipos de data e hora têm métodos:
- isBefore(outraData)
- isAfter(outraData)
- isEqual(outraData) (ou simplesmente equals)
import java.time.LocalDate;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
if (today.isBefore(deadline)) {
System.out.println("Ainda dá tempo!");
} else if (today.isEqual(deadline)) {
System.out.println("Hoje é o deadline!");
} else {
System.out.println("O deadline já passou :(");
}
import java.time.LocalTime;
LocalTime now = LocalTime.now();
LocalTime lunch = LocalTime.of(13, 0);
if (now.isAfter(lunch)) {
System.out.println("O almoço já foi!");
} else {
System.out.println("Ainda há tempo até o almoço.");
}
Importante: você só pode comparar objetos do mesmo tipo (LocalDate com LocalDate, LocalDateTime com LocalDateTime etc.).
4. Prática: exercícios de cálculo de diferenças e verificação de prazos
Exemplo: quantos dias faltam para o deadline da tarefa
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
LocalDate today = LocalDate.now();
LocalDate deadline = LocalDate.of(2025, 7, 1);
long daysLeft = ChronoUnit.DAYS.between(today, deadline);
if (daysLeft > 0) {
System.out.println("Faltam " + daysLeft + " dias para o deadline");
} else if (daysLeft == 0) {
System.out.println("Hoje é o deadline!");
} else {
System.out.println("O deadline passou há " + Math.abs(daysLeft) + " dias");
}
ChronoUnit.DAYS.between() — uma forma prática de obter a quantidade exata de dias entre duas datas (sem considerar meses e anos).
Exemplo: quantos segundos entre dois eventos
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 1, 15, 30, 0);
long seconds = ChronoUnit.SECONDS.between(start, end);
System.out.println("Entre os eventos se passaram " + seconds + " segundos");
Exemplo: calculando a idade de uma tarefa
import java.time.LocalDate;
import java.time.Period;
LocalDate created = LocalDate.of(2025, 5, 20);
LocalDate today = LocalDate.now();
Period period = Period.between(created, today);
System.out.println("A tarefa foi criada " +
period.getDays() + " dias, " +
period.getMonths() + " meses e " +
period.getYears() + " anos atrás.");
Exemplo: duração entre dois Instant
import java.time.Instant;
import java.time.Duration;
Instant start = Instant.now();
// ... fazendo alguma coisa ...
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("A execução levou " + duration.toMillis() + " milissegundos");
5. Particularidades no uso de Period e Duration
Particularidades do Period
- Period calcula a diferença segundo o calendário: entre 28 de fevereiro e 1º de março — 1 dia, mesmo sendo meses diferentes.
- É possível obter separadamente quantidades de anos, meses e dias: getYears(), getMonths(), getDays().
- Se precisar do número total de dias entre datas — use ChronoUnit.DAYS.between().
Particularidades do Duration
- Duration trabalha com tempo exato (horas, minutos, segundos).
- Pode operar com LocalTime, LocalDateTime, Instant.
- Não pode ser usado com datas sem horário (LocalDate) — lançará uma exceção.
Exemplo: diferença entre Period e Duration
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Duration;
import java.time.Period;
LocalDate date1 = LocalDate.of(2025, 2, 28);
LocalDate date2 = LocalDate.of(2025, 3, 1);
Period period = Period.between(date1, date2); // 2 dias (ano bissexto)
long days = java.time.temporal.ChronoUnit.DAYS.between(date1, date2); // 2 dias
System.out.println("Period: " + period.getDays() + " dias");
System.out.println("ChronoUnit: " + days + " dias");
LocalDateTime dt1 = LocalDateTime.of(2025, 6, 1, 23, 0);
LocalDateTime dt2 = LocalDateTime.of(2025, 6, 2, 1, 0);
Duration duration = Duration.between(dt1, dt2); // 2 horas
System.out.println("Duration: " + duration.toHours() + " horas");
6. Usando Duration e Period para exibir a diferença em um formato amigável
Quando você calcula a diferença entre datas ou horas para o usuário, nem sempre é conveniente mostrar “123456 segundos”. Normalmente queremos algo como “2 dias 3 horas 15 minutos”.
Exemplo: exibindo a diferença entre datas e horas
import java.time.LocalDateTime;
import java.time.Duration;
LocalDateTime start = LocalDateTime.of(2025, 6, 1, 14, 0);
LocalDateTime end = LocalDateTime.of(2025, 6, 3, 16, 30);
Duration duration = Duration.between(start, end);
long days = duration.toDays();
long hours = duration.minusDays(days).toHours();
long minutes = duration.minusDays(days).minusHours(hours).toMinutes();
System.out.println("Diferença: " + days + " dias " +
hours + " horas " + minutes + " minutos");
7. Particularidades ao trabalhar com ZonedDateTime e Instant
- A diferença entre dois ZonedDateTime em zonas diferentes é calculada pelo tempo absoluto, não pelo tempo “humano” em cada zona.
- A mudança para horário de verão/inverno pode afetar a diferença em horas entre datas.
Exemplo: diferença entre ZonedDateTime
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.Duration;
ZonedDateTime MinskTime = ZonedDateTime.of(2025, 6, 1, 12, 0, 0, 0, ZoneId.of("Europe/Minsk"));
ZonedDateTime nyTime = ZonedDateTime.of(2025, 6, 1, 5, 0, 0, 0, ZoneId.of("America/New_York"));
Duration diff = Duration.between(nyTime, MinskTime);
System.out.println("Diferença: " + diff.toHours() + " horas");
8. Erros comuns em cálculos com datas e horas
Erro nº 1: confundir Period e Duration.
Se você tentar usar Duration com LocalDate, receberá uma exceção. Para datas use Period; para tempo — Duration.
Erro nº 2: ignorar os fusos horários.
Ao comparar data e hora em fusos diferentes, você pode obter resultados inesperados. É melhor normalizar tudo para um mesmo fuso ou usar Instant.
Erro nº 3: esperar que os métodos plus/minus modifiquem o objeto.
Todos os tipos java.time são imutáveis! Não se esqueça de atribuir o resultado a uma nova variável (por exemplo, today = today.plusDays(1)).
Erro nº 4: usar getDays() de Period achando que é o total de dias.
Na verdade, ele retorna apenas os dias restantes após subtrair anos e meses. Para o total de dias, use ChronoUnit.DAYS.between().
Erro nº 5: comparar objetos de tipos diferentes.
Os métodos isBefore, isAfter, isEqual funcionam apenas para objetos do mesmo tipo (por exemplo, LocalDate com LocalDate).
GO TO FULL VERSION