Novidades do Java 8: JSR 310 – Date and Time API

Fala pessoal!

Esse post é para você que nem conseguiu assimilar as novidades do Java 7 ainda! Sim, porque o Java 8 está logo ali. 😀
Depois de um atraso até bem justificado, o lançamento da versão final do JDK 8 ficou para março/2014, o que já está bem próximo.

Nenhuma outra versão da plataforma Java teve tantas novidades como essa, a 8. A última grande novidade foi a introdução de generics no Java 5, e isso foi em 2004! No meio de todas essas novidades, a que vou falar aqui é uma também muito aguardada.

A JSR 310 foi aprovada pelo comitê executivo em 2007. Há 6 anos! E está esperando um lugar ao sol desde então. Finalmente foi incorporada ao Java 8 e quem quiser brincar antes do lançamento oficial é só baixar uma early access release do JDK 8 no site do Open JDK

A opinião de todos com relação a API atual para manipulação de datas do Java SE é unânime: Ruim demais. A JSR 310, baseada em grande parte no framework JODA-TIME, veio para tentar resgatar nossa dignidade 🙂

Overview

As classes da JSR 310 encontram-se no pacote ‘java.time.*’. Abaixo segue uma breve descrição das principais e em qual cenário cada uma delas deve ser usada:

Classe Descrição
LocalDate Representa uma data simples, sem nenhuma referência a tempo/hora. Ideal para representar eventos onde a hora não é importante: Aniversários, Feriados, etc.
LocalDateTime Uma data completa com data e hora/timezone. Ideal para representar eventos onde a data e também a hora são importantes: Reuniões, compromissos, etc.
LocalTime Representação somente de hora. Nessa classe não há qualquer informação de data, por isso deve ser usada nas ocasiões onde somehte a hora do dia é importante.
Period Uma representação de quantidade de tempo, usando as unidades dia, mes e ano. Essa vai ser a classe usada para calcular por exemplo a quantidade de tempo entre duas datas, mas sempre usando as unidades mencionadas acima. Exemplo: Faltam 7 meses e 22 dias para a Copa do Mundo.
Duration Oferece uma maneira mais precisa de determinar quantidade de tempo, em segundo e nano segundos. É bem parecida com a classe Period, mas vai ser usada em casos onde se faz necessário uma exatidão mais precisa do tempo.
DateTimeFormatter Formatador de objetos date. Vai ser utilizado para formatar objetos LocalDate/LocalDateTime para String e vice-versa.

Exemplos

Algo interessante a ser observado é que todas as classes adotam uma convenção de static factory methods que começam com o prefixo of para construção de objetos. E também como todos os objetos são imutáveis, o padrão Builder é usado extensivamente. O trecho abaixo demonstra como instanciar alguns dos objetos citados na tabela acima:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;

// ...

//criar datas
LocalDate dataAtual = LocalDate.now(); //data atual
LocalDate data1 = LocalDate.of(2014, 3, 22); //22-mar-2014
LocalDate data2 = LocalDate.of(2014, Month.MARCH, 22); //22-mar-2014
LocalDate data3 = Year.of(2010).atMonth(12).atDay(24); //24-dez-2010

//criar objeto com data e hora
LocalDateTime dateTimeAtual = LocalDateTime.now();
LocalDateTime dateTime1 = LocalDateTime.of(2013, Month.MARCH, 21, 21, 10, 1); //21-mar-2013 as 21h10m1s

Alguns casos mais comuns, para transformar String’s em datas e vice-versa:

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

// ...

//criação de um DateTimeFormatter com o padrao dd/MM/yyyy (dia/mes/ano)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

//criar um objeto LocalDatel a partir da String "15/11/2013"
String s = "15/11/2013";
LocalDate data = LocalDate.parse(s, formatter);
System.out.println(data);

//pegar a data atual e transformar em String usando o mesmo formatter
LocalDate dataAtual = LocalDate.now();
String dataAtualString = dataAtual.format(formatter);
System.out.println(dataAtualString);

Se você quer forçar que uma data seja validada, é só usar o enum ResolverStyle.STRICT.

//Criar um fomatter do tipo "STRICT"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
formatter = formatter.withResolverStyle(ResolverStyle.STRICT);

String s = "31/02/2013"; //31 de fevereiro
LocalDate data = LocalDate.parse(s, formatter); //exception!

Agora, vamos supor que você queira saber quanto tempo falta para o reveillon. Observe que a classe Period representa o tempo em unidades determinadas: dias, meses e anos. Entretanto também é possível recuperar somente a diferença em dias:

import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

//...

LocalDate dataInicial = LocalDate.of(2013, Month.NOVEMBER, 15); //data inicial: 15-nov-2013
LocalDate dataFinal = LocalDate.of(2013, Month.DECEMBER, 31); //data final: 31-dez-2013

//Recuperar o periodo completo entre as duas datas
Period periodo = Period.between(dataInicial, dataFinal);
int anos = periodo.getYears();
int meses = periodo.getMonths();
int dias = periodo.getDays();

String s = String.format("Faltam %d ano(s), %d mes(es) e %d dia(s)!", anos, meses, dias);
System.out.println(s); // -> Faltam 0 ano(s), 1 mes(es) e 16 dia(s)!

//diferença somente em dias
long numeroDias = dataInicial.until(dataFinal, ChronoUnit.DAYS);
System.out.println(numeroDias + " dias!"); // -> 46 dias!

Não é tudo mas dá pra ter uma idéia. Não sei se você percebeu, mas uma das diferenças é que agora o mês “janeiro” é representado pelo número ‘1’, e não mais como ‘0’ que nem acontecia na API antiga. Um ser humano evoluído conseguiu perceber que nós não gostamos de tratar meses começando de zero! 🙂

Baixem o JDK 8 e façam seus testes. Ainda há tempo inclusive de sugerir mudanças à equipe da JSR 310!

May the force be with you 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s