Clojure: Trabalhando com datas
Datas no Clojure
Em algumas ocasiões temos que trabalhar com datas em nossos programas. Uma forma nativa e unificada para realizar esse trabalho ajuda muito, já que simplifica a escrita e a manutenção do código.
No caso do Clojure, que roda na JVM, a máquina virtual do Java, podemos usar os comandos nativos dela para obter a informação de data e hora. Porém, nem o Java, nem o Clojure tem um tipo primitivo que guarde data e hora. Para isso, tais linguagens utilizam a codificação da Era UNIX.
Representando tempo
O computador não entende por padrão o que é data e hora para poder utilizar essas informações. Por isso foi criado a Era UNIX, também chamado de Posix Time, Unix epoch ou Unix Timestamp, que conta a quantidade de segundos desde 1 janeiro de 1970 às 00:00:00. Então temos as datas representadas em segundos, assim:
1 janeiro de 1970 às 00:00:00 -> 0 1 janeiro de 1970 às 00:01:00 -> 60 1 janeiro de 1970 às 01:00:00 -> 3600 2 janeiro de 1970 às 00:00:00 -> 86 400
Apesar de ser difícil para nós visualizarmos um número único como uma data, para o computador esta é uma das maneiras mais fáceis, pois para comparar, incrementar ou ver quanto tempo passou, ele poderá utilizar operações simples.
Um pouco de história
No início do Java não existia uma boa maneira de se verificar data e hora. As funções com essa finalidade podiam acabar sendo confusas e demoradas. Para resolver isso, em 2002 começou o desenvolvimento de uma biblioteca chamada JodaTime, que prometia uma maneira simples e unificada para trabalhar com datas dentro do Java.
Quando foi lançada em 2004, ela ganhou muita popularidade por causa da facilidade de uso das funções e rapidez na execução, se mostrando a principal biblioteca de datas do Java. Uma posição que manteve até o lançamento do Java 8, quando foi descontinuada.
Quanto ao Clojure, até o lançamento do Java 8 a melhor maneira de usar datas trabalhando com a linguagem era através do clj-time, uma biblioteca própria para o Clojure, que utilizava as funções da JodaTime para sua execução. Porém, com a descontinuação da JodaTime, ocorreu o mesmo com o clj-time.
No Java 8 foi implementada uma nova maneira para lidar com as datas, a JSR-310. Essa nova API tem funções muito mais rápidas e concisas, uma vez que foi desenvolvida pelo criador da JodaTime, mas sem os problemas que costumavam acontecer com a biblioteca, como poder retornar meses de 1 até 13, ou mostrar o retorno null em vez de 0.
Já no Clojure foi criada uma nova biblioteca para trabalharmos com datas, a clojure.java-time , que implementa as novas mudanças da JSR-310 e utiliza as funções presentes no Java 8.
Atualmente é recomendado que programas feitos e compilados tanto em Java quanto em Clojure, com o JDK (Java development kit) do Java 8 ou posterior, usem a JSR-310 ou o clojure.java-time, porque a JodaTime não receberá mais atualizações.
Também é importante lembrar que quando programas mais antigos forem atualizados, suas funções que utilizam datas e horas devem ser substituídas pelas novas bibliotecas e APIs. Assim a manutenção deles se facilitará no futuro.
Mão na massa
Vamos criar uma aplicação em Clojure para um estacionamento com as seguintes regras de negócio:
- Taxa de R$ 5,00 de entrada no estacionamento
- Taxa de R$ 2,00 por hora adicional
- O estacionamento permite pernoite
Para usar o java-time
, vamos até o project.clj
para incluir a biblioteca nas dependências do projeto.
:dependencies [[org.clojure/clojure "1.10.1"] [clojure.java-time "0.3.2"]]
Armazenaremos esses valores e definiremos uma hora-entrada
de um carro para simular o cálculo. Vamos importar o java-time
para trabalhar com data e a hora.
(use 'java-time)
(def taxa-entrada 5)
(def taxa-por-hora 2)
(def hora-entrada (local-date-time 2021 05 18 8 34))
Para definir a data e a hora do momento atual do sistema, vamos utilizar local-date-time
.
(def hora-saida (local-date-time))
Vamos ainda conferir se tudo está correto exibindo o que foi armazenado na hora-atual
e na hora-saida
.
(println "Horário entrada" hora-entrada)
(println "Horário saída" hora-saida)
Podemos utilizar a função time-between
passando o horário de entrada e a hora de saída para descobrir por quanto tempo o carro ficou estacionado. Para calcular a diferença em minutos, utilizaremos o código :minutes
.
(def duracao (time-between hora-entrada hora-saida :minutes))
Vamos realizar o cálculo do total a pagar.
(def total-a-pagar (+ taxa-entrada (* duracao (float (/ taxa-por-hora 60)))))
Podemos formatar a saída para duas casas decimais com clojure.core/format
e exibir a saída informando o total a pagar.
(def total-com-duas-casas-decimais (clojure.core/format "%.2f" total-a-pagar))
(println "Total a pagar R$" total-com-duas-casas-decimais)
E a saída será:
Conclusão
A biblioteca clojure.java-time
pode nos ajudar a manipular data e hora de forma mais simples nos nossos projetos feitos em Clojure. E aí, curtiu?
Para aprender mais sobre Clojure, veja: