Java Datas e Horas

Vencimento de uma conta, idade de um cliente, quantos dias faltam para o Natal, a hora de uma reunião em outro país: datas aparecem em quase todo programa. O Java tem um pacote moderno e bem feito para isso, o java.time Java 8+. Nesta aula você aprende as classes principais, as contas com datas, a conversão de e para o formato brasileiro dd/MM/yyyy e o que fazer quando a data digitada é inválida.

Você vai aprender
  • LocalDate (data), LocalTime (hora) e LocalDateTime (as duas juntas).
  • Criar datas com now() e of(…), somar com plusDays, comparar com isBefore.
  • O dia da semana em inglês (FRIDAY) e em português (sexta-feira).
  • Medir intervalos: Period, Duration e ChronoUnit.DAYS.between.
  • Formatar e ler datas com DateTimeFormatter.ofPattern("dd/MM/yyyy"), e a DateTimeParseException.
  • Fusos horários com ZonedDateTime e America/Sao_Paulo.
  • Por que não usar as classes antigas Date e Calendar.

Os exemplos rodaram na máquina da Ana no dia 16 de outubro de 2026, no fuso de São Paulo. Quando um exemplo usa now() ("agora"), no seu computador a saída vai mostrar a sua data e a sua hora.


A ideia antes do código

Pense em três objetos da casa da Ana: um calendário de parede (só datas: dia, mês, ano), um relógio (só horas) e a agenda, onde cada compromisso tem data e hora. O java.time tem uma classe para cada um:

ClasseGuardaExemplo impressoUse para
LocalDateData2026-10-16Aniversários, vencimentos, feriados
LocalTimeHora18:30Horário de abertura da loja
LocalDateTimeData e hora2026-11-03T14:45Uma consulta marcada
ZonedDateTimeData, hora e fuso2026-11-03T14:00-03:00[America/Sao_Paulo]Reunião com gente de outro país

"Local" quer dizer "sem fuso horário": é a data e a hora como aparecem no calendário e no relógio de um lugar, sem dizer qual lugar. Todas ficam no pacote java.time e precisam de import.

Objetos que não mudam

Assim como a String, as datas do java.time são imutáveis: plusDays não altera a data, devolve uma nova. Guarde o resultado: data = data.plusDays(1);. Esquecer isso é o erro número 1 com datas (veja Quando dá errado).


LocalDate: a data

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDate hoje = LocalDate.now();
        LocalDate aniversario = LocalDate.of(1997, 3, 14);
        System.out.println("Hoje: " + hoje);
        System.out.println("Nascimento da Ana: " + aniversario);
        System.out.println("Ano: " + hoje.getYear() + ", mês: " + hoje.getMonthValue() + ", dia: " + hoje.getDayOfMonth());
        System.out.println("Mês: " + hoje.getMonth());
        DayOfWeek dia = hoje.getDayOfWeek();
        System.out.println("Dia da semana: " + dia);
        System.out.println("Em português: " + dia.getDisplayName(TextStyle.FULL, Locale.of("pt", "BR")));
        System.out.println("Abreviado: " + dia.getDisplayName(TextStyle.SHORT, Locale.of("pt", "BR")));
        System.out.println("Mês em português: " + hoje.getMonth().getDisplayName(TextStyle.FULL, Locale.of("pt", "BR")));
        System.out.println("Daqui a 30 dias: " + hoje.plusDays(30));
        System.out.println("Mês passado: " + hoje.minusMonths(1));
        System.out.println("Ano bissexto? " + hoje.isLeapYear());
        System.out.println("Dias neste mês: " + hoje.lengthOfMonth());
        System.out.println("Aniversário antes de hoje? " + aniversario.isBefore(hoje));
    }
}
$ java Main.java
Hoje: 2026-10-16
Nascimento da Ana: 1997-03-14
Ano: 2026, mês: 10, dia: 16
Mês: OCTOBER
Dia da semana: FRIDAY
Em português: sexta-feira
Abreviado: sex.
Mês em português: outubro
Daqui a 30 dias: 2026-11-15
Mês passado: 2026-09-16
Ano bissexto? false
Dias neste mês: 31
Aniversário antes de hoje? true
LocalDate.now()
A data de hoje, pelo relógio do computador.
LocalDate.of(1997, 3, 14)
Uma data específica: ano, mês, dia. O mês é o número normal (março = 3).
println(hoje)
Mostra no formato internacional ISO 8601: ano-mês-dia. Para o formato brasileiro, veja Formatar.
getYear(), getMonthValue(), getDayOfMonth()
As partes da data, como números.
getMonth(), getDayOfWeek()
Devolvem enums: OCTOBER, FRIDAY. Os nomes das constantes são em inglês, sempre.
getDisplayName(TextStyle.FULL, Locale.of("pt", "BR"))
O nome para gente ler, no idioma pedido: sexta-feira, outubro. TextStyle.SHORT dá a abreviação (sex.). O Locale foi explicado em Formatar Texto.
plusDays(30), minusMonths(1)
Contas com datas. Existem plus/minus para Days, Weeks, Months, Years. O Java cuida dos meses de 30 e 31 dias e dos anos bissextos.
isBefore, isAfter, isEqual
Comparações: "é antes de?", "é depois de?", "é o mesmo dia?".
Somar meses no fim do mês

LocalDate.of(2026, 1, 31).plusMonths(1) dá 2026-02-28: fevereiro não tem dia 31, e o Java usa o último dia válido em vez de "transbordar" para março.

Missão: a Ana comprou a prazo em 16/10/2026, e a conta vence 30 dias depois. Calcule o vencimento com plusDays e mostre as duas datas no formato brasileiro (o formatador já está pronto): Vencimento: 15/11/2026.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDate compra = LocalDate.of(2026, 10, 16);
        DateTimeFormatter br = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        System.out.println("Compra: " + compra.format(br));
    }
}
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDate compra = LocalDate.of(2026, 10, 16);
        LocalDate vencimento = compra.plusDays(30);
        DateTimeFormatter br = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        System.out.println("Compra: " + compra.format(br));
        System.out.println("Vencimento: " + vencimento.format(br));
    }
}

LocalTime e LocalDateTime

As horas e as datas com hora funcionam do mesmo jeito: now(), of(…), plus…, minus…, isBefore…

import java.time.LocalDateTime;
import java.time.LocalTime;

public class Main {
    public static void main(String[] args) {
        LocalTime abertura = LocalTime.of(8, 0);
        LocalTime fechamento = LocalTime.of(18, 30);
        System.out.println("A loja abre às " + abertura + " e fecha às " + fechamento);
        System.out.println("Agora: " + LocalTime.now());
        System.out.println("Almoço: " + abertura.plusHours(4));
        System.out.println("Fecha depois das 18h? " + fechamento.isAfter(LocalTime.of(18, 0)));

        LocalDateTime consulta = LocalDateTime.of(2026, 11, 3, 14, 45);
        System.out.println("Consulta: " + consulta);
        System.out.println("Remarcada: " + consulta.plusWeeks(1).withHour(9));
        System.out.println("Agora: " + LocalDateTime.now());
        System.out.println("Só a data: " + consulta.toLocalDate() + ", só a hora: " + consulta.toLocalTime());
    }
}
$ java Main.java
A loja abre às 08:00 e fecha às 18:30
Agora: 18:51:24.493991268
Almoço: 12:00
Fecha depois das 18h? true
Consulta: 2026-11-03T14:45
Remarcada: 2026-11-10T09:45
Agora: 2026-10-16T18:51:24.494870731
Só a data: 2026-11-03, só a hora: 14:45
LocalTime.of(8, 0)
Hora e minuto (dá para passar segundos também). Mostrado como 08:00.
LocalTime.now()
Agora, com segundos e frações: 18:51:24.493991268 (até nanossegundos, bilionésimos de segundo).
LocalDateTime.of(2026, 11, 3, 14, 45)
Ano, mês, dia, hora, minuto. Impresso com um T (de time) separando data e hora: 2026-11-03T14:45.
plusWeeks(1).withHour(9)
Encadeamento: uma semana depois e, nessa nova data, com a hora trocada para 9. Os métodos with… trocam um campo (withDayOfMonth, withYear…).
toLocalDate(), toLocalTime()
Separam as duas partes.

Intervalos: Period, Duration e ChronoUnit

"Quantos anos a Ana tem?", "quantos dias faltam?", "quanto tempo dura o expediente?". Para as datas de exemplo não mudarem a cada dia, aqui "hoje" é fixo, com of:

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class Main {
    public static void main(String[] args) {
        LocalDate nascimento = LocalDate.of(1997, 3, 14);
        LocalDate hoje = LocalDate.of(2026, 10, 16);

        Period idade = Period.between(nascimento, hoje);
        System.out.println("Period: " + idade);
        System.out.println("A Ana tem " + idade.getYears() + " anos, "
            + idade.getMonths() + " meses e " + idade.getDays() + " dias");

        long dias = ChronoUnit.DAYS.between(nascimento, hoje);
        System.out.println("Dias de vida: " + dias);
        LocalDate natal = LocalDate.of(2026, 12, 25);
        System.out.println("Faltam " + ChronoUnit.DAYS.between(hoje, natal) + " dias para o Natal");
        System.out.println("Semanas até o Natal: " + ChronoUnit.WEEKS.between(hoje, natal));

        Duration expediente = Duration.between(LocalTime.of(8, 0), LocalTime.of(18, 30));
        System.out.println("Duration: " + expediente);
        System.out.println("Em minutos: " + expediente.toMinutes());
        System.out.println("Horas e minutos: " + expediente.toHours() + "h" + expediente.toMinutesPart() + "min");
        System.out.println("Ao contrário: " + ChronoUnit.DAYS.between(natal, hoje));
    }
}
$ java Main.java
Period: P29Y7M2D
A Ana tem 29 anos, 7 meses e 2 dias
Dias de vida: 10808
Faltam 70 dias para o Natal
Semanas até o Natal: 10
Duration: PT10H30M
Em minutos: 630
Horas e minutos: 10h30min
Ao contrário: -70
FerramentaMedeImpresso comoUse para
Period.between(a, b)Anos, meses e dias "de calendário"P29Y7M2D (Period, 29 Years, 7 Months, 2 Days)Idade, tempo de casa. getYears() é a idade
ChronoUnit.DAYS.between(a, b)O total numa unidade só70 (um long)"Faltam N dias", multas por dia de atraso. Também WEEKS, MONTHS, YEARS, HOURS, MINUTES
Duration.between(a, b)Horas, minutos, segundos exatosPT10H30M (Period of Time, 10 Hours, 30 Minutes)Expedientes, cronômetros. toMinutes(), toHours(), toMinutesPart()

Repare na última linha: a ordem importa. between(natal, hoje) dá -70, porque vai do Natal "para trás". E os nomes são parecidos de propósito: Period é para datas, Duration é para horas.


Formatar e ler: DateTimeFormatter

O formato 2026-10-16 é ótimo para computadores, mas no Brasil se escreve 16/10/2026. O DateTimeFormatter ("formatador de data e hora") converte nos dois sentidos, a partir de um padrão de letras:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDate data = LocalDate.of(2026, 10, 16);
        LocalDateTime consulta = LocalDateTime.of(2026, 11, 3, 14, 45);

        DateTimeFormatter br = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        DateTimeFormatter brHora = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
        DateTimeFormatter extenso = DateTimeFormatter.ofPattern("EEEE, d 'de' MMMM 'de' yyyy");

        System.out.println(data.format(br));
        System.out.println(consulta.format(brHora));
        System.out.println(data.format(extenso));
        System.out.println(data.format(DateTimeFormatter.ofPattern("d/M/yy")));
        System.out.println(data.format(DateTimeFormatter.ofPattern("MMM yyyy")));

        LocalDate natal = LocalDate.parse("25/12/2026", br);
        System.out.println("Lido: " + natal + " (" + natal.getDayOfWeek() + ")");
        LocalDate iso = LocalDate.parse("2026-12-25");
        System.out.println("ISO: " + iso);
    }
}
$ java Main.java
16/10/2026
03/11/2026 14:45
sexta-feira, 16 de outubro de 2026
16/10/26
out. 2026
Lido: 2026-12-25 (FRIDAY)
ISO: 2026-12-25
LetraSignificaExemplo
d / ddDia do mês (com dd, sempre 2 dígitos)3 / 03
M / MMMês em número11 / 11
MMM / MMMMMês em texto, curto / completoout. / outubro
yy / yyyyAno com 2 / 4 dígitos26 / 2026
EEE / EEEEDia da semana curto / completosex. / sexta-feira
HHHora de 0 a 2314
mmMinutos (minúsculo! MM é mês)45
ssSegundos07
'texto'Texto fixo, entre aspas simples'de'

Os nomes em texto (outubro, sexta-feira) saíram em português porque o ofPattern usa o locale padrão, pt_BR na máquina da Ana. Para fixar o idioma, passe o locale: DateTimeFormatter.ofPattern("EEEE", Locale.of("pt", "BR")).

O caminho inverso é o parse ("analisar"): LocalDate.parse("25/12/2026", br) lê o texto usando o mesmo padrão. Sem formatador, LocalDate.parse("2026-12-25") espera o formato ISO.

Quando o texto não é uma data válida: DateTimeParseException

Texto digitado por pessoas vem errado com frequência. Se o texto não combina com o padrão, o parse lança DateTimeParseException (uma unchecked, filha de DateTimeException):

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter br = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        LocalDate data = LocalDate.parse("25-12-2026", br);
        System.out.println(data);
    }
}
$ java Main.java
Exception in thread "main" java.time.format.DateTimeParseException: Text '25-12-2026' could not be parsed at index 2
	at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2108)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2010)
	at java.base/java.time.LocalDate.parse(LocalDate.java:437)
	at Main.main(Main.java:7)

"O texto '25-12-2026' não pôde ser analisado na posição 2": as posições contam a partir de 0, e na posição 2 o padrão esperava / e encontrou -. Com try e catch, o programa pode avisar e seguir. Testando vários textos:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter br = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        String[] textos = {"25/12/2026", "25-12-2026", "32/01/2026", "31/02/2026", "29/02/2028"};
        for (String t : textos) {
            try {
                LocalDate d = LocalDate.parse(t, br);
                System.out.println(t + " -> " + d);
            } catch (DateTimeParseException e) {
                System.out.println(t + " -> erro: " + e.getMessage());
            }
        }
    }
}
$ java Main.java
25/12/2026 -> 2026-12-25
25-12-2026 -> erro: Text '25-12-2026' could not be parsed at index 2
32/01/2026 -> erro: Text '32/01/2026' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
31/02/2026 -> 2026-02-28
29/02/2028 -> 2028-02-29

O dia 32 foi recusado ("valor inválido para dia do mês: valores válidos de 1 a 28/31"). Mas olhe o 31/02/2026: não deu erro, virou 2026-02-28! Por padrão, o formatador é "esperto" (modo SMART): aceita dias de 1 a 31 em qualquer mês e, se o dia não existe naquele mês, usa o último dia válido. Para um formulário, isso é perigoso: a pessoa digitou uma data impossível e o programa aceitou outra. Para recusar, use o modo estrito:

        DateTimeFormatter rigoroso = DateTimeFormatter.ofPattern("dd/MM/uuuu")
                                                     .withResolverStyle(ResolverStyle.STRICT);
$ java Main.java
25/12/2026 -> 2026-12-25
31/02/2026 -> erro: Text '31/02/2026' could not be parsed: Invalid date 'FEBRUARY 31'
29/02/2028 -> 2028-02-29

Dois detalhes: ResolverStyle vem de java.time.format (precisa de import java.time.format.ResolverStyle;), e no modo estrito o ano deve ser escrito uuuu, não yyyy. (A letra y é o "ano da era", que no modo estrito exige também a era, "depois de Cristo"; u é o ano simples.) O ano 2028 é bissexto, por isso 29/02/2028 é válido.


Fusos horários: ZonedDateTime

A Ana marcou uma reunião às 14h, horário de São Paulo, com uma cliente em Lisboa e outra em Tóquio. Que horas são lá? Para isso, a data e a hora precisam de um fuso (ZoneId), identificado por "continente/cidade":

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        System.out.println("Fuso do sistema: " + ZoneId.systemDefault());
        ZonedDateTime reuniao = ZonedDateTime.of(
            LocalDateTime.of(2026, 11, 3, 14, 0), ZoneId.of("America/Sao_Paulo"));
        System.out.println("São Paulo: " + reuniao);
        System.out.println("Lisboa:    " + reuniao.withZoneSameInstant(ZoneId.of("Europe/Lisbon")));
        System.out.println("Manaus:    " + reuniao.withZoneSameInstant(ZoneId.of("America/Manaus")));
        System.out.println("Tóquio:    " + reuniao.withZoneSameInstant(ZoneId.of("Asia/Tokyo")));
        DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM HH:mm z");
        System.out.println(reuniao.withZoneSameInstant(ZoneId.of("Europe/Lisbon")).format(f));
        System.out.println("Agora: " + ZonedDateTime.now());
    }
}
$ java Main.java
Fuso do sistema: America/Sao_Paulo
São Paulo: 2026-11-03T14:00-03:00[America/Sao_Paulo]
Lisboa:    2026-11-03T17:00Z[Europe/Lisbon]
Manaus:    2026-11-03T13:00-04:00[America/Manaus]
Tóquio:    2026-11-04T02:00+09:00[Asia/Tokyo]
03/11 17:00 WET
Agora: 2026-10-16T18:51:55.388086963-03:00[America/Sao_Paulo]
ZoneId.of("America/Sao_Paulo")
O fuso de Brasília. Os nomes vêm de um banco de dados mundial de fusos (o tz database), que guarda também a história dos horários de verão de cada lugar.
ZonedDateTime.of(localDateTime, zona)
"Estas data e hora, neste lugar".
-03:00
A diferença para o UTC, o horário de referência mundial: São Paulo está 3 horas atrás. Z (de "zero", em Lisboa) quer dizer exatamente UTC.
withZoneSameInstant(zona)
"O mesmo instante, visto de outro lugar": às 14h de São Paulo são 17h em Lisboa, 13h em Manaus e 2h do dia seguinte em Tóquio.
z no padrão
A abreviação do fuso (WET, Western European Time).

Use LocalDate/LocalDateTime quando o fuso não importa (um aniversário é no mesmo dia em qualquer lugar). Use ZonedDateTime quando o mesmo instante precisa ser mostrado em lugares diferentes, ou quando o horário de verão pode afetar a conta. Para registrar "o instante exato em que algo aconteceu" (num log, num banco de dados), existe também o Instant, um ponto na linha do tempo em UTC.


Por que não usar Date e Calendar

Antes do Java 8, as datas eram feitas com java.util.Date e java.util.Calendar. Você ainda vai vê-las em código antigo e em tutoriais velhos. Veja por que elas foram substituídas:

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

public class Main {
    public static void main(String[] args) {
        Date agora = new Date();
        System.out.println(agora);
        System.out.println("Ano pelo Date: " + agora.getYear());

        Calendar prova = new GregorianCalendar(2026, 10, 16);
        System.out.println("Mês 10 é: " + prova.getTime());

        Calendar estranha = new GregorianCalendar(2026, 1, 31);
        System.out.println("31 de fevereiro virou: " + estranha.getTime());
    }
}
$ java Main.java
Main.java:9: warning: [deprecation] getYear() in Date has been deprecated
        System.out.println("Ano pelo Date: " + agora.getYear());
                                                    ^
1 warning
Fri Oct 16 18:51:56 GMT-03:00 2026
Ano pelo Date: 126
Mês 10 é: Mon Nov 16 00:00:00 GMT-03:00 2026
31 de fevereiro virou: Tue Mar 03 00:00:00 GMT-03:00 2026
  • O ano: getYear() devolve 126, os anos desde 1900. O próprio javac avisa que o método está obsoleto (deprecated).
  • Os meses começam em 0: no Calendar, janeiro é 0. O "mês 10" que a Ana escreveu pensando em outubro virou novembro.
  • Datas impossíveis viram outras, em silêncio: o mês 1 é fevereiro, e o "31 de fevereiro" virou 3 de março, sem exceção nenhuma.
  • São mutáveis: um Date passado para um método pode ser alterado lá dentro, mudando a data de quem chamou.
  • Um Date não é uma data: é um instante com hora, e o toString mistura o fuso do computador.

Em código novo, use sempre o java.time. Se precisar conversar com uma biblioteca antiga, há conversões prontas: date.toInstant() e Date.from(instant).


Quando dá errado

A data não mudou depois do plusDays
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        LocalDate prova = LocalDate.of(2026, 10, 16);
        prova.plusDays(7);
        System.out.println("Prova adiada para: " + prova);
    }
}
$ java Main.java
Prova adiada para: 2026-10-16

O que aconteceu: datas do java.time são imutáveis. O plusDays(7) criou uma data nova (23/10) e ela foi jogada fora. Não há erro nem aviso.

Como resolver: guarde o resultado: prova = prova.plusDays(7);.

DateTimeException: Invalid date 'FEBRUARY 30'
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        LocalDate prova = LocalDate.of(2026, 2, 30);
        System.out.println(prova);
    }
}
$ java Main.java
Exception in thread "main" java.time.DateTimeException: Invalid date 'FEBRUARY 30'
	at java.base/java.time.LocalDate.create(LocalDate.java:461)
	at java.base/java.time.LocalDate.of(LocalDate.java:277)
	at Main.main(Main.java:5)

O que aconteceu: ao contrário do Calendar, o LocalDate.of recusa datas que não existem.

Como resolver: confira os valores. Se eles vêm do usuário, trate DateTimeException com try/catch.

"could not be parsed at index N"

O que aconteceu: o texto não segue o padrão do formatador. O índice diz em que caractere (contando de 0) a leitura falhou.

Como resolver: confira o separador (/ ou -), a quantidade de dígitos (dd exige 05, não 5; para aceitar os dois, use d) e a ordem (dia/mês/ano ou ano-mês-dia).

Os minutos saíram como mês

O que aconteceu: no padrão, MM (maiúsculo) é mês e mm (minúsculo) é minuto. "HH:MM" mostra a hora e o mês.

Como resolver: "HH:mm" para horas, "dd/MM/yyyy" para datas.


Referência

CódigoO que faz
LocalDate.now(), LocalDate.of(a, m, d)Hoje; uma data específica
LocalTime.of(h, min), LocalDateTime.of(a, m, d, h, min)Hora; data e hora
plusDays/Weeks/Months/Years(n), minus…Somar e subtrair (devolve uma data nova)
getDayOfWeek(), getMonth()Enums em inglês: FRIDAY, OCTOBER
getDisplayName(TextStyle.FULL, Locale.of("pt","BR"))Nome em português: sexta-feira
isBefore, isAfter, isEqualComparar
Period.between(a, b)Anos, meses, dias (getYears())
ChronoUnit.DAYS.between(a, b)Total de dias
Duration.between(h1, h2)Horas, minutos, segundos (toMinutes())
DateTimeFormatter.ofPattern("dd/MM/yyyy")Formatador brasileiro
data.format(f) / LocalDate.parse(texto, f)Data → texto / texto → data
.withResolverStyle(ResolverStyle.STRICT) + uuuuRecusar datas impossíveis como 31/02
ZonedDateTime.of(ldt, ZoneId.of("America/Sao_Paulo"))Data e hora num fuso
withZoneSameInstant(zona)O mesmo instante em outro fuso

Exercícios

1. Uma semana depois

Complete para obter a data uma semana depois de hoje:

LocalDate proxima = hoje.;

2. Padrão brasileiro com hora

Complete o padrão para mostrar 03/11/2026 14:45:

DateTimeFormatter.ofPattern("")

3. Quantos dias

Complete para calcular os dias entre inicio e fim:

long dias = ChronoUnit..between(inicio, fim);

4. O que LocalDate.of(2026, 10, 16).getDayOfWeek() mostra no println?

5. LocalDate d = LocalDate.of(2026, 1, 10); d.plusDays(5); System.out.println(d); mostra:

6. Para calcular a idade de uma pessoa em anos, o mais adequado é:

Missão final: a Ana nasceu em 14/03/1997 e "hoje" é 16/10/2026. Calcule a idade dela com Period.between(…).getYears() e o dia da semana em que ela nasceu, em português, com getDisplayName(TextStyle.FULL, Locale.of("pt", "BR")). A saída deve ser A Ana tem 29 anos e Ela nasceu numa sexta-feira.

import java.time.LocalDate;
import java.time.Period;
import java.time.format.TextStyle;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDate nascimento = LocalDate.of(1997, 3, 14);
        LocalDate hoje = LocalDate.of(2026, 10, 16);
        // calcule a idade e o dia da semana
    }
}
import java.time.LocalDate;
import java.time.Period;
import java.time.format.TextStyle;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDate nascimento = LocalDate.of(1997, 3, 14);
        LocalDate hoje = LocalDate.of(2026, 10, 16);
        int anos = Period.between(nascimento, hoje).getYears();
        String dia = nascimento.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.of("pt", "BR"));
        System.out.println("A Ana tem " + anos + " anos");
        System.out.println("Ela nasceu numa " + dia);
    }
}

Resumo

  • Use o java.time: LocalDate (data), LocalTime (hora), LocalDateTime (as duas), ZonedDateTime (com fuso).
  • Crie com now() ou of(…); o mês é o número normal (outubro = 10).
  • As datas são imutáveis: data = data.plusDays(1);.
  • getDayOfWeek() dá FRIDAY; para português, getDisplayName(TextStyle.FULL, Locale.of("pt", "BR")).
  • Intervalos: Period (anos/meses/dias), ChronoUnit.DAYS.between (total), Duration (horas/minutos).
  • DateTimeFormatter.ofPattern("dd/MM/yyyy") formata e lê; texto inválido lança DateTimeParseException. Para recusar 31/02, use ResolverStyle.STRICT com uuuu.
  • Date e Calendar são antigos: ano a partir de 1900, meses a partir de 0, datas impossíveis aceitas em silêncio. Evite.