Trabalho avançado com datas e horas em Java: de LocalDate a manipulações complexas
No Java moderno (a partir da versão 8), o padrão de facto para trabalhar com datas e horas é o pacote java.time. Ele substituiu os obsoletos java.util.Date e java.util.Calendar, oferecendo objetos imutáveis, segurança em threads e uma API intuitiva. Neste artigo, abordaremos técnicas avançadas: trabalho com fusos horários, cálculos precisos de diferenças, ajustadores personalizados e formatação complexa.
1. Manipulações de datas com TemporalAdjusters
Uma das capacidades mais poderosas do java.time é a interface TemporalAdjuster. Ela permite realizar ajustes complexos em datas — por exemplo, encontrar a "próxima terça-feira" ou o "último dia do mês".
A classe TemporalAdjusters (observe o plural) contém métodos estáticos prontos:
firstDayOfMonth()— primeiro dia do mês;lastDayOfMonth()— último dia do mês;next(DayOfWeek.FRIDAY)— próximo dia da semana especificado;previousOrSame(DayOfWeek.MONDAY)— segunda-feira anterior ou atual.
Exemplo: vamos encontrar a data da próxima quarta-feira após 15 de março de 2024.
import java.time.LocalDate;import java.time.DayOfWeek;import java.time.temporal.TemporalAdjusters;
public class TemporalExample { public static void main(String[] args) { LocalDate date = LocalDate.of(2024, 3, 15); LocalDate nextWednesday = date.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY)); System.out.println("Próxima quarta-feira: " + nextWednesday); // Saída: 2024-03-20 }}Você pode criar seus próprios ajustadores implementando a interface funcional TemporalAdjuster. Isso é especialmente útil para lógica de negócios: "primeiro dia útil do mês" ou "última sexta-feira do trimestre".
2. Trabalho com fusos horários e ZonedDateTime
Aplicações globais devem considerar os fusos horários. A classe ZonedDateTime combina data, hora e zona (ZoneId).
Exemplo: converter o horário de Nova York para Berlim, considerando horário de verão/inverno.
import java.time.ZonedDateTime;import java.time.ZoneId;import java.time.format.DateTimeFormatter;
public class ZoneExample { public static void main(String[] args) { ZonedDateTime newYork = ZonedDateTime.now(ZoneId.of("America/New_York")); ZonedDateTime berlin = newYork.withZoneSameInstant(ZoneId.of("Europe/Berlin"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z"); System.out.println("Nova York: " + newYork.format(formatter)); System.out.println("Berlim: " + berlin.format(formatter)); }}Importante: para obter todas as zonas disponíveis, use ZoneId.getAvailableZoneIds(). Evite abreviações de três letras (EST, PST) — elas são ambíguas. Sempre use o formato continente/cidade (por exemplo, Asia/Tokyo).
3. Cálculos precisos de diferenças: ChronoUnit e Duration
Para calcular a diferença entre datas em Java, existem duas abordagens:
ChronoUnit— para diferenças em unidades de calendário (dias, meses, anos);Duration— para intervalos de tempo precisos (segundos, nanossegundos).
Exemplo: quantos dias e meses faltam para o Ano Novo?
import java.time.LocalDate;import java.time.temporal.ChronoUnit;
public class DiffExample { public static void main(String[] args) { LocalDate today = LocalDate.now(); LocalDate newYear = LocalDate.of(today.getYear() + 1, 1, 1);
long days = ChronoUnit.DAYS.between(today, new