Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Praticando Java: data e hora

Praticando Java: data e hora

Data e hora - Apresentação

Olá, meu nome é Jacqueline Oliveira, sou engenheira de software e instrutora na Alura.

Audiodescrição: Jaqueline se identifica como uma mulher de pele branca. Possui cabelos longos e alguns reflexos louros. Veste uma blusa verde. Ao fundo, há uma parede lisa e um armário à direita, iluminados em tons de azul.

O que aprenderemos?

Neste curso, vamos abordar a manipulação de data e hora utilizando as APIs do Java.

Vamos explorar tópicos como os tipos específicos localDate, localTime e localDateTime. Faremos a atribuição de valores de forma diferenciada utilizando os métodos now(), parse() e off(). Também realizaremos a manipulação e verificação das datas com os métodos isBefore(), isAfter(), plus(), minus(), entre outros que serão apresentados.

Além disso, abordaremos o cálculo de diferenças de datas e horas utilizando period() e duration().

Este conteúdo é bastante interessante e será de grande auxílio no trabalho com datas. Contamos com a sua participação!

Data e hora - Data e hora

É comum ouvir que trabalhar com data e hora no Java é complexo. No entanto, isso é um mito.

No passado, quando utilizávamos bibliotecas como Date e Calendar do pacote java.util, realmente era mais complicado. Contudo, o Java agora possui uma nova API, o java.time, que simplificou bastante o trabalho com datas.

Explorando classes para manipulação de datas

Existem algumas classes que são muito utilizadas na programação:

Para todos esses tipos, há métodos para atribuir valores e criar datas, que veremos na prática:

Aplicando exemplos práticos

Vamos entender isso, na prática. Abriremos a IDE IntelliJ, no arquivo Principal.java, e faremos alguns exemplos para ilustrar.

Suponhamos que queiramos manipular datas de compra e vencimento, algo comum em aplicações de vendas. Para criar uma data, podemos usar LocalDate e nomear a variável como dataCompra.

Também precisamos importar a classe LocalDate:

Principal.java:

import java.time.LocalDate;

public class Principal {
    public static void main(String[] args) {
        LocalDate dataCompra
    }
    
}

Para que ela receba a data de hoje, utilizaremos LocalDate.now(), que retorna a data atual. Isso também se aplica a LocalTime e LocalDateTime.

LocalDate dataCompra = LocalDate.now();

Vamos descer para a linha seguinte.

Se quisermos definir a data da primeira parcela, podemos criar uma variável dataPrimeiraParcela e determinar o ano, mês e dia usando LocalDate.of(). Por exemplo, podemos definir 15 de maio de 2025 como a data da primeira parcela.

LocalDate dataPrimeiraParcela = LocalDate.of(2025, 5, 15);

Manipulando e imprimindo datas

Além dos métodos now(), of() e parse(), podemos manipular essas datas, adicionando dias, semanas, meses ou anos, utilizando métodos que começam com plus.

Por exemplo, se quisermos que a variável dataSegundaParcela receba uma data 30 dias após a primeira parcela, utilizaremos plusDays(30).

LocalDate dataSegundaParcela = dataPrimeiraParcela.plusDays(30);

Podemos imprimir esses valores usando System.out.println() para a data da compra, data da primeira parcela e data da segunda parcela.

System.out.println("Data compra: " + dataCompra);
System.out.println("Data primeira parcela: " + dataPrimeiraParcela);
System.out.println("Data segunda parcela: " + dataSegundaParcela);

Vamos executar a aplicação para ver como será exibido no terminal:

Data compra: 2025-03-13
Data primeira parcela: 2025-05-15
Data segunda parcela: 2025-06-14

Notaremos que a data da compra foi 13 de março de 2025. A primeira parcela está com a data que foi determinada, 15 de maio de 2025. Por fim, após 30 dias, a segunda parcela ficou para 14 de junho de 2025.

Ou seja, o sistema já adicionou os dias automaticamente, exatamente como configuramos.

Usamos o plusDays(), mas existem outros métodos disponíveis para todos. Por exemplo:

Verificando datas

Além de adicionar e subtrair datas, podemos fazer verificações, como se uma data é antes ou depois de outra com os seguintes métodos:

Por exemplo, podemos verificar se a data da primeira parcela é igual à data atual usando isEqual(LocalDate.now()), que retorna um valor booliano. Acima dos prints, criaremos o seguinte bloco para verificar se a data atual é o dia do vencimento:

if (dataPrimeiraParcela.isEqual(LocalDate.now())) {
    System.out.println("Hoje é o dia do vencimento");
} else {
    System.out.println("Ainda não está no dia do vencimento");
}

Ao executar, o terminal informou que não é dia do vencimento.

Ainda não está no dia do vencimento.

Podemos alterar esse código para verificar se a data atual é anterior ao dia do vencimento, utilizando isBefore():

if (dataPrimeiraParcela.isBefore(LocalDate.now())) {
    System.out.println("Anterior ao dia do vencimento");
} else {
    System.out.println("Superior ao dia do vencimento");
}

Ao executar, o terminal informou que a data atual é superior ao dia do vencimento, pois a primeira parcela é depois do dia de hoje.

Superior ao dia do vencimento.

Formatando datas

O LocalDate segue o padrão ISO 8601, que exibe datas no formato ano-mês-dia. No entanto, podemos querer mostrar em um padrão diferente.

Podemos formatar a data usando DateTimeFormatter para criar o formato no padrão brasileiro. Por exemplo, abaixo dos prints, podemos criar um DateTimeFormatter chamado formato, usando DateTimeFormatter.ofPattern("dd/MM/yyyy"), onde dd/MM/yyyy define o padrão dia/mês/ano.

Utilizamos MM maiúsculo para definir meses, pois mm minúsculo define os minutos.

DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd/MM/yyyy");

Na linha seguinte, criaremos um print no qual aplicaremos esse formato à variável dataCompra com .format(formato):

System.out.println("Data compra formatada: " + dataCompra.format(formato));

Ao executar a aplicação, a data da compra formatada aparecerá no formato dia/mês/ano.

Data compra formatada: 13/03/2025

Trabalhando com fusos horários

Além de podermos formatar as datas no padrão desejado, escolhendo se queremos apenas o mês e o ano, se queremos o ano com quatro dígitos ou com dois, e definir exatamente o padrão através do DateTimeFormatter.ofPattern(), também podemos trabalhar por meio da orientação a fusos horários.

Vamos supor que queiramos trabalhar com uma data baseada em um fuso horário e que possamos verificar qual seria essa data em outro fuso horário. Para fazer isso, vamos criar uma data de conclusão da compra para armazenar o momento exato da conclusão da compra.

Queremos observar esse horário de conclusão tanto no Brasil quanto no padrão dos Estados Unidos. Para isso, utilizaremos a classe ZonedDateTime, que é um DateTime baseado no fuso horário.

Vamos criar uma variável dataConclusaoCompra e definir como ZonedDateTime.now(), que representa o momento atual.

ZonedDateTime dataConclusaoCompra = ZonedDateTime.now();

Para converter para o horário de outro país, precisamos fazer essa troca. Primeiro, imprimiremos essa data de conclusão sem formatação.

System.out.println("Data conclusão compra: " + dataConclusaoCompra);

Para verificar a data e horário de conclusão dessa compra se estivéssemos em Nova York, criaremos uma nova variável ZonedDateTime chamada dataCompraNy. Para transformar, utilizaremos dataConclusaoCompra.withZoneSameInstant() para coletar o mesmo instante.

ZonedDateTime dataCompraNy = dataConclusaoCompra.withZoneSameInstant();

Para selecionar o local entre parênteses, usaremos ZoneId.of(), e a partir disso, teremos algumas possibilidades. Vamos pressionar "Enter" para mover o ZoneId.of() para a linha de baixo e tornar a explicação mais clara.

ZonedDateTime dataCompraNy = dataConclusaoCompra.withZoneSameInstant(
    ZoneId.of());

Se colocarmos o mouse em cima do ZoneId, o editor exibe uma caixa de texto com a documentação, que mostra as normas e locais de onde é possível buscar. Nessa documentação, ao clicar no item “ZoneRules”, podemos verificar a origem desejada.

No nosso caso, quero buscar informações de Nova York. Portanto, colocaremos o trecho "America/New_York", entre aspas duplas.

ZonedDateTime dataCompraNy = dataConclusaoCompra.withZoneSameInstant(
    ZoneId.of(America/New_York));

Na próxima linha, imprimiremos essa data.

System.out.println("Data conclusão compra NY: " + dataCompraNy);

Ao executar, podemos comparar os resultados. A data de conclusão da compra foi 13 de março de 2025, às 8h41. Já em Nova York, foi às 7h41.

Data conclusão compra: 2025-03-13T08:41:30.492264500-03:00[America/Sao_Paulo]

Data conclusão compra NY: 2025-03-13T07:41:30.492264500-04:00[America/New_York]

Ou seja, o sistema aplicou automaticamente o fuso horário e entendeu que Nova York está uma hora atrás do Brasil.

Conseguimos trabalhar com datas orientadas ao fuso horário, permitindo trocas e verificações. Para explorar mais recursos, trabalharemos com data e hora, utilizando DateTimeFormatter e ZonedDateTime para formatar dados e trabalhar com dados diferenciados.

Calculando a diferença entre datas e horas

Agora, faremos um exercício sobre o cálculo de diferença entre datas e horas, utilizando Duration e Period.

O Duration é geralmente usado para horas. Vamos fazer um teste para ver nosso horário de trabalho (quanto tempo de expediente estamos trabalhando).

Para isso, abaixo do último print, criaremos duas variáveis de horas usando LocalTime. Chamaremos uma de inicio e definiremos como LocalTime.of(9, 0) (09 horas e 0 minutos). A outra será fim, definida como LocalTime.of(17, 30).

LocalTime inicio = LocalTime.of(9, 0);
LocalTime fim = LocalTime.of(17, 30);

Para calcular a duração entre inicio e fim, utilizaremos a classe Duration, que faz verificações sobre duração.

Duration duracao = Duration

Colocando o ponto depois do tipo de uma variável, conseguimos visualizar uma lista com os métodos disponíveis para ele. Neste caso, queremos saber a duração entre duas horas — ou seja, qual será a duração entre o horário de início e o de fim. Para isso, usaremos between(inicio, fim).

Duration duracao = Duration.between(inicio, fim);

Na linha seguinte, usaremos um System.out.println() para exibir: "A duração do expediente é..." seguido de Duracao.toHours() e Duracao.toMinutesPart(). Isso significa que recolheremos o total de horas e depois o que sobrou em minutos.

System.out.println("Duração do expediente: " + duracao.toHours() + 
                   " horas e " + duracao.toMinutesPart() + " minutos.");

Ao executar, o terminal informa:

A duração do seu expediente é 8 horas e 30 minutos.

Podemos fazer a mesma verificação de duração com relação a datas. Pulando uma linha, criaremos um LocalDate para a data de pagamento, chamado dataPagamento, usando LocalDate.parse() no formato ISO, por exemplo, "2025-10-30".

LocalDate dataPagamento = LocalDate.parse("2025-10-30");

Queremos calcular o período entre a data de compra e a data de pagamento, para saber quanto tempo tivemos de prazo para pagar. Criaremos uma variável chamada periodo, que calculará o tempo entre essas duas datas usando o método Period.between(), passando a data de compra e a data de pagamento como parâmetros.

Period periodo = Period.between(dataCompra, dataPagamento);

Exibiremos a mensagem com um System.out.println(), coletando a diferença em dias com periodo.getDays().

System.out.println("Diferença em dias: " + periodo.getDays());

Poderíamos pegar anos e meses, concatenando os valores .getDays(), .getYears() e .getMonths().

Executando a aplicação, ele mostra uma diferença de 17 dias.

Diferença em dias: 17

No entanto, a compra está como 30 de março e o pagamento como 30 de outubro. Ou seja, o método getDays() está pegando apenas os dias da diferença, não o total em dias.

Desafio

Precisamos verificar na documentação do JavaDoc se o método realmente traz o que queremos. O correto é concatenar meses e dias. Ele mostra 17, que é 30 menos 13, mas precisamos usar métodos para somar.

A resolução desse problema será seu desafio! Acesse a documentação do JavaDoc e tente resolvê-lo.

Conclusão

Exploramos bastante os tipos data e hora, a formatação de datas, fusos horários, além de cálculos e manipulações de datas e horários. Esperamos que você tenha gostado desse conteúdo.

Não deixe de avaliar este curso! Em caso de dúvidas, compartilhe no fórum ou no Discord. Te esperamos no próximo curso.

Sobre o curso Praticando Java: data e hora

O curso Praticando Java: data e hora possui 23 minutos de vídeos, em um total de 16 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas