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 2).

Publicado no grupo Random-PT
Horas do dia
    Então vamos em frente. A próxima entidade após a data é a hora do dia, representada pela classe LocalTime . Um exemplo clássico é representar o horário de funcionamento de uma loja, digamos, das 7h00 às 23h00. As lojas abrem neste horário em todo o país, mas os horários reais variam dependendo do fuso horário.     LocalTime é uma classe de valor que armazena apenas a hora, sem data ou fuso horário associado. Ao adicionar ou subtrair um período de tempo, ele será cortado à meia-noite. Ou seja, 20h mais 6 horas são 2h. Usar LocalTime é semelhante a LocalDate : LocalTime time = LocalTime.of(20, 30); int hour = date.getHour(); // 20 int minute = date.getMinute(); // 30 time = time.withSecond(6); // 20:30:06 time = time.plusMinutes(3); // 20:33:06     modificadores podem funcionar com LocalTime , mas as operações de tempo geralmente não são tão complexas a ponto de serem necessários modificadores.
Combinando data e hora
    A próxima classe que veremos é LocalDateTime . Esta classe de valor é uma combinação de LocalDate e LocalTime . Representa data e hora, sem fuso horário.      LocalDateTime pode ser criado diretamente ou combinando data e hora: LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE, 10, 20, 30); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(20, 30); LocalDateTime dt4 = date.atTime(time);     A terceira e quarta opções usam o método atTime() , que fornece uma maneira flexível de combinar data e hora. A maioria das classes de sistema de data e hora possuem métodos "at" que podem ser usados ​​ao combinar seu objeto com outro para criar um mais complexo. Os outros métodos da classe LocalDateTime são semelhantes aos de LocalDate e LocalTime . Padrões de nomenclatura de métodos semelhantes tornam a API mais fácil de aprender . Esta tabela lista todos os prefixos de métodos envolvidos: Uma biblioteca intuitiva e robusta para trabalhar com horas e datas está finalmente disponível em Java (Parte 2).  - 1
Instante
    Quando lidamos com datas e horas, geralmente trabalhamos com anos, meses, dias, horas, minutos, segundos. No entanto, este é apenas um modelo de tempo que pode ser chamado de “humano”. O segundo modelo comumente usado é o tempo “máquina” ou “contínuo”. Neste modelo, um ponto no eixo do tempo é representado por um número grande. Esta abordagem simplifica os algoritmos de cálculo, e é usada para armazenar o tempo no sistema operacional Unix , onde o tempo é representado pelo número de segundos que se passaram desde 1º de janeiro de 1970. Da mesma forma, em Java , o tempo é armazenado como o número de milissegundos que se passaram desde 1º de janeiro de 1970. A abordagem de máquina para cálculos de tempo na API java.time é fornecida pela classe de valor Instant . Ele fornece a capacidade de representar um ponto em um eixo de tempo sem todas as informações que o acompanham, como fuso horário. Na verdade, esta classe contém o número de nanossegundos que se passaram desde a meia-noite de 1º de janeiro de 1970. Instant start = Instant.now(); // произведем вычисления Instant end = Instant.now(); assert end.isAfter(start); //машина времени не сработала     Normalmente, a classe Instant é usada para armazenar e comparar pontos no tempo quando você precisa armazenar quando algum evento aconteceu, mas não se importa com o fuso horário em que aconteceu. Na maioria dos casos, é mais interessante o que não podemos fazer com a classe Instant do que o que podemos fazer com ela. Por exemplo, as seguintes linhas de código lançarão exceções: instant.get(ChronoField.MONTH_OF_YEAR); instant.plus(6, ChronoUnit.YEARS);     As exceções ocorrem porque o objeto instantâneo armazena apenas o número de nanossegundos e não fornece a capacidade de trabalhar com unidades de tempo que são mais úteis para os humanos. Para usar outras unidades de medida, você deve especificar pelo menos um fuso horário.
Fusos horários
    O princípio dos fusos horários foi desenvolvido na Inglaterra quando a invenção das ferrovias e as melhorias em outros meios de comunicação permitiram que as pessoas viajassem distâncias suficientes para que as diferenças no tempo solar fossem perceptíveis. Até então, cada aldeia e cidade vivia de acordo com o seu tempo, que na maioria das vezes era medido pelo relógio de sol. Esta imagem mostra um exemplo das dificuldades que isso levou - os ponteiros vermelhos do relógio mostram a hora de Greenwich e os ponteiros pretos mostram a hora local, que difere em 10 minutos: O sistema de fuso horário foi desenvolvido, substituindo a hora solar local Uma biblioteca intuitiva e robusta para trabalhar com horas e datas está finalmente disponível em Java (Parte 2).  - 2     . Mas o facto principal é que os fusos horários são criados pelos políticos e são frequentemente utilizados para demonstrar controlo político sobre uma área. Como qualquer política, as regras relacionadas aos fusos horários muitas vezes desafiam a lógica. E também, essas regras podem mudar, e muitas vezes mudam, sem qualquer aviso. As regras de fuso horário são compiladas por um grupo internacional que publica o banco de dados de fuso horário da IANA . Ele contém o identificador de cada região da Terra e o histórico de mudanças de fuso horário para ela. Os identificadores se parecem com “Europa/Londres” ou “América/Nova_Iorque” . Antes do lançamento da API java.time , a classe TimeZone era usada para representar um fuso horário . Agora ZoneId é usado . Existem duas diferenças principais entre eles. Primeiro, ZoneId é imutável, o que permite armazenar objetos desta classe em variáveis ​​estáticas, entre outras coisas. Em segundo lugar, as próprias regras são armazenadas na classe ZoneRules , e não no próprio ZoneId , e para obtê-las você precisa chamar o método getRules() no objeto da classe ZoneId . Uma característica comum de todos os fusos horários é um deslocamento fixo de UTC/Greenwich . Na maioria das vezes você usa isso quando fala sobre diferenças de horário entre cidades diferentes, como "Nova York está 5 horas atrás de Londres". A classe ZoneOffset , descendente de ZoneId , representa a diferença horária com o meridiano principal que passa por Greenwich, em Londres. Do ponto de vista do desenvolvedor, seria ótimo não ter que lidar com fusos horários e suas complexidades. A API java.time permite que você faça isso enquanto for possível. Sempre que possível, utilize as classes LocalDate, LocalTime, LocalDateTime e Instant . Onde você não pode ficar sem fusos horários, use a classe ZonedDateTime . Classe ZonedDateTimepermite converter datas e horas de unidades de medida humanas, que vemos em calendários e relógios, em unidades de máquina. Como resultado, você pode criar um ZonedTimeDate a partir da classe Local ou da classe Instant : ZoneId zone = ZoneId.of("Europe/Paris"); LocalDate date = LocalDate.of(2014, Month.JUNE, 10); ZonedDateTime zdt1 = date.atStartOfDay(zone); Instant instant = Instant.now(); ZonedDateTime zdt2 = instant.atZone(zone);     Um dos recursos mais desagradáveis ​​dos fusos horários é o chamado horário de verão. Com a mudança do horário de verão de e para Greenwich, a diferença de fuso horário com Greenwich muda duas vezes (ou mais) por ano, geralmente aumentando na primavera e diminuindo no outono. Quando isso acontece, temos que trocar todos os relógios da nossa casa. Nas classes java.time , os dados de deslocamento são representados como "transformações de deslocamento" . Na primavera isso causa uma “lacuna” no tempo, quando alguns valores de tempo são impossíveis, e no outono, ao contrário, alguns valores de tempo ocorrem duas vezes. Tudo isso é suportado pela classe ZonedDateTime por meio de seus métodos de fábrica e métodos de conversão. Por exemplo, adicionar um dia adiciona um dia lógico, que pode ser representado por mais ou menos de 24 horas se mudarmos para o horário de verão ou voltarmos. Da mesma forma, o método atStartOfDay() tem esse nome porque não podemos garantir que o dia começará exatamente à meia-noite - devemos levar em consideração o intervalo de tempo ao mudar para o horário de verão. E uma última dica em relação ao horário de verão. Se quiser demonstrar que foi contabilizada a sobreposição de tempo durante a transição do verão para o inverno (quando o mesmo valor de tempo aparece duas vezes), você pode usar um dos dois métodos especiais projetados para tais situações: Esses métodos retornarão o valor anterior ou posterior zdt = zdt.withEarlierOffsetAtOverlap(); zdt = zdt.withLaterOffsetAtOverlap();     value , se o objeto ficar preso em uma sobreposição durante a transição do verão para o inverno. Em todas as outras situações, os valores de retorno serão os mesmos.
Intervalos de tempo
    Todas as classes que discutimos anteriormente funcionam como pontos na linha do tempo. Duas classes de valores adicionais são necessárias para representar intervalos de tempo. A classe Duration representa um período de tempo, medido em segundos e nanossegundos. Por exemplo, “23,6 segundos”. A classe Período representa um período de tempo medido em anos, meses e dias. Por exemplo - “3 anos, 2 meses e 6 dias”. Esses intervalos podem ser adicionados ou subtraídos de uma data ou hora: Period sixMonths = Period.ofMonths(6); LocalDate date = LocalDate.now(); LocalDate future = date.plus(sixMonths);
Formatação e análise
    Um pacote inteiro foi projetado para formatar e exibir datas e horas - java.time.format . O pacote gira em torno da classe DateTimeFormatter e sua fábrica DateTimeFormatterBuilder . As formas mais comuns de criar um formatador são através de métodos estáticos e constantes em DateTimeFormatter , incluindo:
  • Constantes para formatos comuns descritos em ISO, como ISO_LOCAL_DATE.
  • Padrões identificados por letras, como ofPattern("dd/MM/uuuu").
  • Estilos localizados, como ofLocalizedDate(FormatStyle.MEDIUM).
    Depois de criar um formatador, você normalmente o utiliza passando-o para o método de classe de data apropriado: DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu"); LocalDate date = LocalDate.parse("24/06/2014", f); String str = date.format(f);     Dessa forma, o código responsável pela formatação da saída de data é isolado em uma classe separada. Se você precisar especificar separadamente a localidade para formatação de data, use o método do formatador withLocale(Locale) . As classes responsáveis ​​pelo calendário, fuso horário e entrada/saída de números fracionários possuem métodos semelhantes. Se precisar de mais opções de ajuste, consulte a documentação da classe DateTimeFormatterBuilder , que permite criar formatadores complexos passo a passo. Ele também permite definir a análise de texto sem distinção entre maiúsculas e minúsculas, ignorar alguns erros de análise, definir deslocamentos e elementos opcionais.
Resultado final
     A API java.time é um novo modelo abrangente para trabalhar com data e hora no Java SE 8 . Ele leva as ideias e implementações do Joda-Time para o próximo nível e, finalmente, permite que os desenvolvedores evitem o uso de java.util.Date e Calendar . Agora trabalhar com datas e horários pode ser divertido!      Artigo original
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION