Trabalho Avançado com Datas e Horas em Java: do básico ao profissionalismo
\n\nTrabalhar com datas e horas é uma das tarefas essenciais de qualquer aplicação empresarial. Em Java, por muito tempo o padrão foi o complicado java.util.Date e java.util.Calendar, mas com o lançamento do Java 8 a situação mudou drasticamente. A nova API java.time (JSR-310) ofereceu aos desenvolvedores um conjunto de ferramentas poderoso, thread-safe e intuitivo. Neste artigo, abordaremos técnicas avançadas de trabalho com datas e horas que serão úteis para todo desenvolvedor Java.
1. Fundamentos da API java.time: LocalDate, LocalTime, LocalDateTime
\n\nO primeiro passo para um trabalho profissional é entender as três classes básicas que substituíram as antigas equivalentes:
\n\n- \n
- LocalDate — data sem hora (ano, mês, dia). \n
- LocalTime — hora sem data (horas, minutos, segundos, nanossegundos). \n
- LocalDateTime — combinação de data e hora sem vínculo com fuso horário. \n
// Obtendo data e hora atuais\nLocalDate today = LocalDate.now(); // 2025-03-21\nLocalTime now = LocalTime.now(); // 14:30:15.123\nLocalDateTime current = LocalDateTime.now(); // 2025-03-21T14:30:15.123\n\n// Criando uma data específica\nLocalDate birthDate = LocalDate.of(1990, Month.JUNE, 15);\nLocalTime meetingTime = LocalTime.of(10, 30, 0);\n\n// Manipulações com datas\nLocalDate nextWeek = today.plusWeeks(1);\nLocalDate lastMonth = today.minusMonths(1);\n\nEssas classes são imutáveis — qualquer operação retorna um novo objeto. Isso garante segurança em threads e previsibilidade do código.
\n\n2. Trabalhando com fusos horários: ZonedDateTime e ZoneId
\n\nAplicações globais não podem ignorar os fusos horários. Para isso, a java.time oferece a classe ZonedDateTime.
// Hora atual em UTC\nZonedDateTime utcNow = ZonedDateTime.now(ZoneOffset.UTC);\n\n// Hora em um fuso horário específico\nZoneId moscowZone = ZoneId.of("Europe/Moscow");\nZonedDateTime moscowTime = ZonedDateTime.now(moscowZone);\n\n// Conversão entre fusos\nZonedDateTime nyTime = moscowTime.withZoneSameInstant(ZoneId.of("America/New_York"));\n\n// Obtendo o offset\nZoneOffset offset = moscowTime.getOffset(); // +03:00\n\nDica profissional: sempre armazene datas em UTC no servidor e converta para o fuso horário local apenas na camada de apresentação (UI). Isso evitará problemas com horário de verão/inverno.
\n\n3. Parsing e formatação de datas: DateTimeFormatter
\n\nUma das tarefas mais comuns é converter string em data e vice-versa. O DateTimeFormatter oferece recursos flexíveis.
Formatação básica
\n\nDateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");\nLocalDateTime dateTime = LocalDateTime.parse("21.03.2025 14:30:00", formatter);\nString formatted = dateTime.format(formatter); // "21.03.2025 14:30:00"\n\nPadrões avançados
\n\n// ISO-8601\nDateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;\nString isoDate = dateTime.format(isoFormatter); // "2025-03-21T14:30:00"\n\n// Formatação localizada\nDateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ITALY);\nString italianDate = dateTime.format(italianFormatter); // "21 marzo 2025"\n\n// Formato personalizado com campos textuais\nDateTimeFormatter customFormatter = new DateTimeFormatterBuilder()\n .appendValue(ChronoField.YEAR)\n .appendLiteral(" ano, ")\n .appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL)\n .appendLiteral(" ")\n .appendValue(ChronoField.DAY_OF_MONTH)\n .toFormatter();\nString custom = dateTime.format(customFormatter); // "2025 ano, março 21"\n\nÉ importante lembrar: DateTimeFormatter também é imutável e thread-safe.