CodeGym /Cursos /JAVA 25 SELF /Visão geral da API java.time e diferenças em relação às A...

Visão geral da API java.time e diferenças em relação às APIs antigas

JAVA 25 SELF
Nível 13 , Lição 1
Disponível

1. Contexto histórico: como se trabalhava com datas antes do Java 8

Nos tempos remotos (antes do Java 8), para trabalhar com datas e horas usava-se as classes java.util.Date, java.util.Calendar e, para formatação — java.text.SimpleDateFormat. Era aquele caso em que programadores do mundo todo suspiravam em uníssono e, rangendo os dentes, escreviam algo como:

import java.util.Date;

Date now = new Date();
System.out.println(now); // Vai imprimir algo estranho como "Wed Jun 05 14:15:22 MSK 2025"

Parece simples, mas na prática não era nada tão bonito. Aqui estão apenas algumas das “alegrias” do API antigo:

  • Date — objeto mutável (mutable). Ele podia ser alterado inadvertidamente, o que frequentemente levava a bugs.
  • Os meses em Date e Calendar começavam em zero (janeiro é 0, dezembro — 11), enquanto os dias começavam em um.
  • SimpleDateFormat não era thread-safe: se duas threads formatassem datas simultaneamente, resultados inesperados podiam ocorrer.
  • Uma enorme quantidade de métodos foi marcada como @Deprecated (obsoletos), e a IDE vivia te assustando com avisos amarelos.
  • Trabalhar com fusos horários era uma verdadeira dor: era fácil confundir hora local e UTC, e a mudança para horário de verão/inverno nem vale lembrar.

Exemplo doloroso

import java.util.Date;

Date date = new Date(2025, 5, 1); // ano 2025, mês 5 (junho?), dia 1
System.out.println(date); // Não é o que você espera!

2. O surgimento do java.time: uma nova abordagem

Em 2014 ficou claro: o API antigo não era apenas incômodo — era perigoso. Por isso, surgiu no Java o novo pacote — java.time, que implementa a especificação JSR‑310. Essa API foi inspirada na popular biblioteca Joda-Time e rapidamente se tornou o padrão de fato.

Pacotes e classes principais

  • java.time — pacote principal, onde ficam todas as novas classes para data e hora.
  • java.time.format — para formatação e análise (parsing) de datas e horas.
  • java.time.temporal — para operações temporais mais avançadas.
  • java.time.zone — para trabalhar com fusos horários.

Aqui estão os principais protagonistas da nova API:

Classe Para quê? Exemplo de uso
LocalDate
Apenas data (ano, mês, dia) Aniversário, sem horário
LocalTime
Apenas hora (horas, minutos, segundos) Horário da reunião, sem data
LocalDateTime
Data e hora, sem fuso horário Evento local
ZonedDateTime
Data e hora com fuso horário Reunião em Minsk no horário local
Instant
Instante absoluto (UTC) Carimbo de evento no log
Duration
Intervalo de tempo (horas, minutos, seg.) Duração da chamada
Period
Período (anos, meses, dias) Tempo de serviço, idade

Exemplo: criar uma data de forma moderna

import java.time.LocalDate;

LocalDate today = LocalDate.now();
System.out.println(today); // Por exemplo: "2025-06-05"

3. Vantagens da nova API

Imutabilidade (immutable)

Todas as classes de java.time são imutáveis. Isso significa: se você criou um objeto LocalDate, não é possível alterá-lo. Qualquer operação (por exemplo, adicionar um dia) retorna um novo objeto.

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);

System.out.println(today);    // 2025-06-05
System.out.println(tomorrow); // 2025-06-06

Tratamento explícito de fusos horários

No API antigo era fácil esquecer em qual fuso horário a data estava. Em java.time tudo é explícito: se precisar de fuso horário — use ZonedDateTime; se não precisar — use LocalDateTime.

import java.time.ZonedDateTime;
import java.time.ZoneId;

ZonedDateTime MinskTime = ZonedDateTime.now(ZoneId.of("Europe/Minsk"));
System.out.println(MinskTime); // 2025-06-05T14:23:45+03:00[Europe/Minsk]

Métodos práticos para cálculos e comparação

LocalDate today = LocalDate.now();
LocalDate nextMonth = today.plusMonths(1);
boolean isAfter = LocalDate.now().plusDays(1).isAfter(today); // true

Formatação e análise (parsing)

Formatação e análise — por meio de DateTimeFormatter (detalhes — na próxima aula):

import java.time.format.DateTimeFormatter;

LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
String formatted = today.format(formatter); // "05.08.2025"

4. Compatibilidade: como conviver com o código antigo

No mundo real, com muita frequência é preciso trabalhar com bibliotecas ou sistemas antigos que usam Date e Calendar. Felizmente, a nova API é amigável ao legado: é possível converter os tipos antigos para os novos e vice-versa.

Conversão DateInstant

import java.util.Date;
import java.time.Instant;

// Date → Instant
Date legacyDate = new Date();
Instant instant = legacyDate.toInstant();

// Instant → Date
Date dateBack = Date.from(instant);

Conversão CalendarZonedDateTime

import java.util.Calendar;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.util.Date;

// Calendar → ZonedDateTime
Calendar calendar = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(
        calendar.toInstant(),
        calendar.getTimeZone().toZoneId()
);

// ZonedDateTime → Calendar
Calendar calBack = Calendar.getInstance();
calBack.setTime(Date.from(zdt.toInstant()));

Tabela: mapeamento entre classes antigas e novas

Classe antiga Classe nova Comentário
java.util.Date
Instant
Tempo absoluto
java.util.Calendar
ZonedDateTime
Data e hora com fuso horário
java.text.SimpleDateFormat
DateTimeFormatter
Formatação/análise de datas

5. Prática: primeiros passos com java.time

Suponha que você tenha um usuário com data de nascimento. Vamos salvar e exibir essa data:

import java.time.LocalDate;

public class UserProfile {
    private String name;
    private LocalDate birthDate;

    public UserProfile(String name, LocalDate birthDate) {
        this.name = name;
        this.birthDate = birthDate;
    }

    public void printProfile() {
        System.out.println("Nome: " + name);
        System.out.println("Data de nascimento: " + birthDate);
    }
}

public class Main {
    public static void main(String[] args) {
        UserProfile user = new UserProfile("Alisa", LocalDate.of(1998, 12, 25));
        user.printProfile();
    }
}

Saída:

Nome: Alisa
Data de nascimento: 1998-12-25

6. Comparação: API antiga vs API nova

Exemplo: adicionar uma semana à data de nascimento

Modo antigo (Date/Calendar):

import java.util.Calendar;

Calendar cal = Calendar.getInstance();
cal.set(1998, Calendar.DECEMBER, 25);
cal.add(Calendar.WEEK_OF_YEAR, 1);
System.out.println(cal.getTime()); // Trabalhoso e pouco intuitivo

Modo novo (java.time):

import java.time.LocalDate;

LocalDate birthDate = LocalDate.of(1998, 12, 25);
LocalDate nextWeek = birthDate.plusWeeks(1);
System.out.println(nextWeek); // 1999-01-01

Na nova API o código é mais curto, mais simples e mais seguro.

7. Erros comuns ao trabalhar com java.time

Erro nº 1: esquecer que os objetos são imutáveis.
Se você chamar date.plusDays(1); e não guardar o resultado, a data original continuará a mesma.

Erro nº 2: confundir LocalDate com LocalDateTime.
LocalDate armazena apenas a data (ano, mês, dia), enquanto LocalDateTime também inclui a hora. Não confunda quando precisar tratar horas e minutos.

Erro nº 3: usar classes antigas em projetos novos.
Se possível — sempre use java.time. As classes antigas servem apenas para compatibilidade.

Erro nº 4: manipulação incorreta de fusos horários.
Se for necessário armazenar um evento importante para diferentes regiões, use ZonedDateTime ou pelo menos Instant. LocalDateTime não contém informações de fuso horário!

Erro nº 5: tentar comparar diretamente LocalDate e LocalDateTime.
São tipos diferentes; não é possível compará-los diretamente. Primeiro, converta para o mesmo tipo.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION