JavaRush /Blogue Java /Random-PT /Uma biblioteca intuitiva e robusta para trabalhar com hor...
theGrass
Nível 24
Саратов

Uma biblioteca intuitiva e robusta para trabalhar com horas e datas está finalmente disponível em Java (Parte 1).

Publicado no grupo Random-PT
Java     finalmente possui uma maneira intuitiva e confiável de trabalhar com datas e horas. Os princípios de data e hora são fundamentais em muitas aplicações. Várias coisas, como datas de nascimento, datas de aluguel, horários de eventos e horários de funcionamento da loja, são todas baseadas em datas e horários, mas o Java SE não forneceu uma maneira conveniente de trabalhar com eles. A partir do Java SE 8 , havia um conjunto de pacotes java.time - que fornecem uma API bem estruturada para trabalhar com datas e horas.
Fundo
    Quando o Java foi lançado, na versão 1.0 , a única classe para trabalhar com datas e horas era java.util.Date . A primeira coisa que os desenvolvedores notaram foi que não representa uma “data”. Na verdade, representa um momento no tempo, com precisão de milissegundos, medido a partir da data de 1º de janeiro de 1970. No entanto, com base no fato de que o método toString() de Date exibe a data e a hora no fuso horário especificado nas configurações java da máquina , alguns desenvolvedores concluíram erroneamente que Date pode funcionar com fusos horários. Consertar essa classe acabou sendo tão difícil (ou tão preguiçoso) que na versão 1.1 tivemos que adicionar uma nova classe - java.util.Calendar . Infelizmente, a classe Calendar acabou não sendo muito melhor que Date . Aqui está uma pequena lista de problemas existentes em sua implementação:
  • Mutável. Aulas como data e hora devem ser imutáveis.
  • Compensações. Os anos em Data começam em 1900, os meses em ambas as classes começam em zero.
  • Nomes. A data não é realmente uma "data" e o Calendário não é um calendário.
  • Formatação. A formatação funciona apenas com Data, não com Calendário, e não é thread-safe.
    Em 2001 foi criado o projeto Joda-Time . Seu objetivo era simples: criar uma biblioteca de alta qualidade para trabalhar com datas e horas em Java . Demorou algum tempo, mas a versão 1.0 foi finalmente lançada e rapidamente se tornou muito popular e amplamente utilizada. Com o tempo, os desenvolvedores exigiram cada vez mais que uma biblioteca de conveniência semelhante fosse fornecida como parte do JDK . Com a participação de Michael Nascimento Santos do Brasil foi lançado o projeto JSR-310 , que é o processo oficial de criação e integração de uma nova API para trabalhar com datas e horas no JDK .
Análise
A nova API java.time contém 5 pacotes:
  • java.time – o pacote base contendo objetos para armazenar valores
  • java.time.chrono - fornece acesso a diferentes calendários
  • java.time.format - formatação e reconhecimento de data e hora
  • java.time.temporal – bibliotecas de baixo nível e funcionalidades avançadas
  • java.time.zone - classes para trabalhar com fusos horários
    A maioria dos desenvolvedores usará principalmente o pacote base e a formatação, e talvez java.time.temporal . Assim, embora 68 novos tipos tenham sido adicionados, os desenvolvedores usarão apenas cerca de um terço deles.
datas
    A classe LocalDate é uma das mais importantes da nova API . Ele contém um valor imutável que representa uma data. Você não pode definir a hora ou o fuso horário. O nome "local" pode ser familiar para você no Joda-Time e vem originalmente do padrão ISO-8601 . Significa precisamente a ausência de fuso horário. Essencialmente, LocalDate é a descrição de uma data, como “5 de abril de 2014”. A hora real desta data será diferente dependendo do seu fuso horário. Por exemplo, na Austrália esta data será 10 horas mais cedo do que em Londres e 18 horas mais cedo do que em São Francisco. A classe LocalDate possui todos os métodos comumente necessários: LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     Em nosso exemplo, vemos uma data criada usando um método de fábrica (todos os construtores são privados). Em seguida, pedimos alguns dados ao objeto. Observe que as enumerações Month e DayOfWeek foram projetadas para tornar o código mais legível e confiável. No exemplo a seguir veremos como modificar a data. Como a classe é imutável, o resultado serão novos objetos, mas o original permanecerá como estava. LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     Estas são alterações relativamente simples, mas muitas vezes você precisa fazer modificações de datas mais complexas. Existe um mecanismo especial para isso na API java.time - TemporalAdjuster . O seu objetivo é fornecer uma ferramenta integrada que permita manipular datas, por exemplo obtendo um objeto correspondente ao último dia do mês. Alguns deles estão incluídos na API , mas você pode adicionar os seus próprios. Usar modificadores é muito fácil, mas requer importações estáticas: import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     Usar modificadores simplifica muito seu código. Ninguém quer ver muita manipulação manual de datas. Se algum tipo de manipulação de data ocorrer diversas vezes em seu projeto, escreva seu próprio modificador e sua equipe poderá utilizá-lo como um componente já escrito e testado.
Hora e data como valores
    Vale a pena gastar um pouco de tempo entendendo o que torna o LocalDate um valor. Valores são tipos de dados simples e completamente intercambiáveis; quando são iguais, a identidade dos objetos perde o sentido. Um exemplo clássico de classe de valor é String . Comparamos strings usando equals() e não nos importamos se os objetos são idênticos quando comparados com o operador == . A maioria das classes para trabalhar com datas e horas também são valores. Portanto, compará-los usando o operador == é uma má ideia, conforme indicado na documentação. Para aqueles interessados ​​em aprender mais, confira minha definição recente de VALJOs , que descreve um conjunto estrito de regras que objetos de valor em Java devem seguir , incluindo imutabilidade, métodos de fábrica e definição adequada de equals() , hashCode , toString() , e compareTo.() .
Calendários alternativos
    A classe LocalDate , como todas as classes principais em java.time , está vinculada a um único calendário - conforme descrito no padrão ISO-8601 . O padrão 8601 descreve o calendário padrão mundial, também conhecido como calendário gregoriano. Um ano padrão inclui 365 dias, um ano bissexto - 366. Cada quarto ano é um ano bissexto, a menos que seja divisível por 100 ou divisível por 400. O ano anterior ao primeiro ano de uma nova era é considerado zero para facilitar o cálculo. A primeira consequência de este ser o sistema padrão é que os resultados nem sempre correspondem aos calculados usando GregorianCalendar . A classe GregorianCalendar possui uma mudança integrada para o sistema Juliano para todas as datas anteriores a 15 de outubro de 1582. No sistema Juliano, cada quarto ano era um ano bissexto, sem exceção. A questão é: como a transição de um sistema para outro é um fato histórico, por que o java.time não a modela? Sim, porque diferentes países mudaram para o sistema gregoriano em momentos diferentes, e considerando apenas a data da transição do Vaticano obteremos dados incorrectos para a maioria dos outros países. Por exemplo, o Império Britânico, incluindo as colónias da América do Norte, mudou para o calendário gregoriano em 14 de setembro de 1752, quase 200 anos depois. A Rússia não alterou o seu calendário até 14 de Fevereiro de 1918, e a transição da Suécia é geralmente um assunto obscuro. Como resultado, o significado real das datas anteriores a 1918 varia muito, dependendo das circunstâncias. Os autores do código LocalDate tomaram uma decisão completamente racional de não modelar a transição do calendário juliano para o calendário gregoriano, a fim de evitar discrepâncias. A segunda consequência do uso da ISO-8601 como calendário padrão em todas as classes principais é que um conjunto adicional de classes é necessário para lidar com os calendários restantes. A interface Cronologia é a base para trabalhar com calendários alternativos, permitindo encontrar o calendário desejado pelo nome da localidade. Java 8 vem com 4 calendários adicionais - Budista Tailandês, Mingguo (Taiwanês), Japonês e Islâmico. Outros calendários podem vir com programas. Cada calendário possui uma classe de data especial, como ThaiBuddhistDate , MinguoDate , JapaneseDate e HijrahDate . Faz sentido usá-los em aplicações altamente localizadas, como as do governo japonês. Uma interface adicional, ChronoLocalDate , é usada como uma abstração central das quatro classes acima junto com LocalDate, que permite escrever código independente do tipo de calendário usado. Embora esta abstração exista, seu uso não é recomendado. Entender por que essa abstração não é recomendada é importante para entender como funciona toda a API java.time . O resultado final é que a maior parte do código escrito sem referência a um calendário específico acaba não funcionando. Por exemplo, você não pode ter certeza de que há 12 meses em um ano, mas alguns desenvolvedores adicionam 12 meses e pensam que adicionaram um ano inteiro. Você não pode ter certeza de que todos os meses contêm aproximadamente o mesmo número de dias - no calendário copta há 12 meses de 30 dias e 1 mês de cinco ou seis dias. Além disso, você não pode ter certeza de que o número do próximo ano será 1 a mais que o atual, porque no calendário japonês os anos são contados a partir da proclamação do próximo imperador (neste caso, até 2 dias do mesmo mês podem pertencer a anos diferentes). A única maneira de escrever código funcional e de alta qualidade que funcione com vários calendários ao mesmo tempo é que o núcleo do seu código, que executa todas as operações em datas e horas, deve ser escrito usando um calendário padrão e somente ao inserir/exibir datas caso seja convertido para outros sistemas de calendário. Ou seja, é recomendado utilizar LocalDate para armazenamento e todas as manipulações de data na sua aplicação. E somente ao localizar datas de entrada e saída você deve usar ChronoLocalDate , que geralmente é obtido da classe de calendário armazenada no perfil do usuário. É verdade que a maioria dos aplicativos não precisa de uma localização tão séria. Caso precise de uma explicação mais detalhada de tudo descrito neste capítulo, seja bem-vindo à documentação da classe ChronoLocalDate .      Continuação do artigo      Artigo original
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION