sábado, 1 de novembro de 2008

Tutorial: Como Obter e Formatar Datas em Java

Mês passado, publiquei um extenso tutorial sobre como obter e formatar datas em javascript, dividido em duas partes: parte 01 e parte 02. Reparei que algumas pessoas, ao lidar com o mesmo problema, porém em java, têm iguais dificuldades, devido à maneira específica com que o objeto Date é tratado no momento de se formatar uma data.
Em java, uma data é comumente armazenada no objeto java.util.Date. Como em muitas outras lingugens, este objeto retém uma certa quantidade de informações internas além da data em si. Esta é representada por um número gigantesco e único, correspondete à quantidade de milissegundos decorridos desde a data convencionada como inicial (dependendo do caso, pode ser 01/01/1900, às 00:00:00, ou outra data parecida, anterior ou posterior, dependendo de qual objeto e qual linguagem você esteja utilizando) até a data do momento em que o objeto foi instanciado na memória. Por isso, converter este número imenso em uma data inteligível, com dia, mês, dia da semana, ano, hora, minuto, segundo e centésimo... isto é uma operação interna do objeto que envolve diversos cálculos, ou seja, não é simplesmente recuperar um dado guardadinho ali dentro.
Embora pareça complicado, formatar datas em java é muito simples!! Existe uma classe especial só para fazer o trabalho de tradução da formatação de data que o desenvolvedor deseja para o conteúdo que o objeto Date armazena em si. Esta classe é o SimpleDateFormat, do pacote java.text.
O SimpleDateFormat tem dois métodos de especial interesse:

  • format - recebe um objeto Date e retorna uma String formatada, segundo a configuração desejada;
  • parse - faz o inverso; recebe uma String e, baseado na configuração desejada, interpreta-a, gerando um objeto Date correspondete.
Como você já deve ter notado, para se formatar uma data é preciso, antes, informar como é esse formato que imaginamos. Em outras palavras, é preciso configurar o formatador. Felizmente, o SimpleDateFormat foi construído baseado em abstract factory (um padrão de projeto prórpio para este tipo de situação), e sua configuração é muito fácil!! Basta construí-lo passando uma String, com caracteres que representam as partes do formato de data que queremos. Exemplos:

SimpleDateFormat formatador1 = new SimpleDateFormat("dd/MM/yyyy")
(formataria datas para: 25/12/2008)
SimpleDateFormat formatador2 = new SimpleDateFormat("HH:mm:ss")
(formataria datas para apenas a hora: 23:45:02)

Apenas esta String é o suficiente para o SimpleDateFormat entender como você deseja o formato de sua data. Todavia, opcionalmente você ainda pode definir em que localidade você está! Isto é útil para dados de formatação que dependam de idioma e país, como o nome dos dias da semana ou do mês. Para fazer isto, basta acrescentar mais um argumento no construtor do SimpleDateFormat, o objeto Locale, do pacote java.util. O locale deve ser construído com as siglas da língua e do país, como nos exemplos:

Locale local1 = new Locale("pt", "BR"); //Português, Brasil
SimpleDateFormat formatador1 = new SimpleDateFormat("EEE", local1)
(formataria datas para: "Seg")
Locale local2 = new Locale("fr", "FR"); //Francês, França
SimpleDateFormat formatador1 = new SimpleDateFormat("EEE", local2)
(formataria datas para: "Lun")

No caso acima, "E" significa o nome do dia da semana. Ele foi repetido 3 vezes porque queríamos exatos 3 caracteres do nome. Para saber quais letras significam o que e como manipular a quantidade de caracteres de cada item, verifique a lista completa na documentação da Sun: aqui.

Exemplo 01: formatando uma data:

//Configurando tudo...
Locale local = new Locale("pt", "BR");
String dataHoraConfig = "dd/MM/yyyy HH:mm:ss";
SimpleDateFormat formatador = new SimpleDateFormat(dataHoraConfig, local);

//Obtendo e formatando a data...
Date data = new Date(); //Data do exato instante em que o objeto é carregado
String dataFormatada = formatador.format(data);

Isto cospirá algo como "01/11/2008 03:08:50".

Exemplo 02: recuperando o objeto Date correspondente a uma data formatada:

//Configurando tudo...
Locale local = new Locale("pt", "BR");
String dataHoraConfig = "dd/MM/yyyy HH:mm:ss";
SimpleDateFormat formatador = new SimpleDateFormat(dataHoraConfig, local);

//Obtendo o objeto Date...
String dataString = "01/11/2008 03:08:50";
Date data = formatador.parse(dataString);

Cuidado!

  • O parse pode falhar, então é preciso tratar a exceção ParseException;
  • O objeto Date tem sempre a precisão do milésimo de segundo. Se a sua String não chega até lá, o objeto terá os itens de maior precisão iniciados em zero. Exemplo: se a String informar apenas o ano "1980", o objeto Date será algo como "01/01/1980 00:00:00".

É isso aí, gente!! Espero ter ajudado!! Gostou?? Não gostou?? Comente!!

4 comentários:

athanazio disse...

Calendar.getInstance() rulez !!

O Pajé disse...

Ótima lembraça!!
De fato, o Calendar é bem melhor para manipular (e comparar!!) datas do que o Date. Mas tem vezes que o Date tem que ser usado...

Exemplo: o Hibernate mapeia campos timestamp ou datetime ou date (dependendo do banco) para java.util.Date.

Outro caso: você tem uma tela que precisa mostrar a data atual na tela. Daí é mais fácil dar um new Date() e mandar ver no SimpleDateFormat.

Bom, ao menos eu vejo assim... Com corda ou sem corda??

athanazio disse...

Calendar.getInstance().getTime()
retorna um Date =) com a data atual hehehe.

manipular datas com Calendar ajuda a manter os dentes quando comecar a ter problemas com horario de verao e fuso horario...

O Pajé disse...

Ok, vc venceu, batata-frita :-DDDD

(Mas não diga isso ao Hibernate, ehehehe...)

Eu mesmo fiz uma API que formata datas com formatos compostos pré-fixados para utilizar em aplicações minhas, e lá tem um conversor Date-Calendar-Date para facilitar ainda mais a vida...