Use o código e tenha 10% de desconto!

Datas e horas Conceitos fundamentais e as APIs do Java

Hugo Kotsubo

Prefácio

Toda aplicação precisa, em algum momento, lidar com datas. Seja com os casos mais simples, como uma data de nascimento no cadastro de usuários, até os mais complexos, como um rastreamento completo de todos os eventos ocorridos com determinado produto, desde a sua confecção até a venda, com data e hora exatas em que cada etapa ocorreu, além de geração de relatórios das vendas do último mês, e assim por diante.

Inicialmente, pensamos ser algo simples, afinal, datas e horas são coisas tão banais no cotidiano que nem nos damos conta da complexidade escondida por trás destes conceitos. E é aí que mora o perigo. Ao tratar algo complexo com uma abordagem simplista, corremos o risco de não pensar em todos os erros que podem acontecer. Simplesmente porque nem sequer imaginamos que eles possam ocorrer.

Um exemplo: imagine uma rede varejista que tem sua matriz em São Paulo, mas possui um e—commerce que entrega em todo o Brasil. Suponha que um gerente pediu um relatório de todas as compras feitas no site, em janeiro de 2018, em todo o país. Uma das compras foi feita por um cliente que estava em Manaus, no dia 31 de janeiro de 2018, às 23:00 (horário local). Porém, esta compra não aparece no relatório.

Depois de muita investigação, descobre-se que a aplicação que extraiu o relatório está convertendo todas as datas para o fuso horário de São Paulo. E 31 de janeiro de 2018, às 23:00 em Manaus é equivalente a 1º de fevereiro de 2018, às 01:00 em São Paulo (lembre-se de que São Paulo estava em horário de verão neste dia, daí a diferença de 2 horas). Por isso, aquela compra não está aparecendo no relatório de janeiro.

Muitas vezes nem é culpa do desenvolvedor - ao menos não diretamente - pois, dependendo da API utilizada, essas conversões acontecem internamente, "por debaixo dos panos", sem que o desenvolvedor sequer perceba. E podemos até debater quem é o real culpado: o desenvolvedor, por não conhecer os detalhes intrínsecos que envolvem a programação com datas, ou os criadores da API utilizada, por não terem feito algo mais fácil de usar e entender? Mas o fato é que no fim das contas o problema deve ser corrigido. Claro que há uma decisão de negócio envolvida (considerar o horário do cliente ou o horário de São Paulo?), mas, uma vez tomada esta decisão, o desenvolvedor deve saber como alterar seu código para que siga a regra desejada.

Para saber exatamente o que fazer, é essencial ter um conhecimento maior sobre todos os conceitos e detalhes envolvendo datas e horas. Sem saber como funcionam os fusos horários e demais conceitos, e como sua linguagem ou framework trabalha com eles, não é possível escrever um código confiável. Como eu sei que estou considerando este ou aquele fuso horário? Como meu código vai se comportar no exato momento em que ocorre a mudança para o horário de verão? Como eu sei que estou usando a data correta?

Este livro tratará estas e muitas outras questões envolvendo datas. A primeira parte explicará todos os conceitos importantes do ponto de vista do desenvolvedor de software. Portanto, serão desconsiderados conceitos como relatividade e outros não diretamente relacionados à manipulação de datas em aplicações. Por ser mais conceitual, esta parte não focará em nenhuma tecnologia ou linguagem específica, sendo interessante a todos os desenvolvedores.

No restante do livro cobriremos as APIs da linguagem Java, começando com java.util.Date e java.util.Calendar, e por fim a API java.time, introduzida no Java 8, e que é muito superior à API antiga, em vários aspectos que serão explicados ao longo do livro.

Muitos argumentam que, por existir uma nova API, não é mais necessário aprender Date e Calendar. Apesar de concordar que as aplicações devam usar o java.time sempre que possível, ainda há muito código legado e bibliotecas antigas — porém muito utilizadas — que dependem de Date e Calendar, e é importante saber como elas funcionam para que a migração seja feita da forma correta. Por serem limitadas e cheias de problemas, há muito código que usa estas classes de maneiras não convencionais – justamente para tentar contornar suas limitações, ou até mesmo por desconhecimento – ou que não se comportam de maneira muito intuitiva, por isso nem sempre é trivial migrar para a nova API.

E se você não programa em Java, ainda assim poderá aproveitar um pouco da segunda e terceira partes do livro. Apesar de terem muito código, estes capítulos também aprofundarão alguns conceitos e discutirão casos de uso e situações práticas que não aparecem na primeira parte.

Sobre o autor

Hugo Kotsubo é Bacharel em Ciência da Computação pela USP e desenvolvedor Java desde 2000, com foco em aplicações web. Possui certificação SCJP e atualmente trabalha com Java no front-end e às vezes no back-end. Também flerta com outras linguagens (Python, Ruby, Shell Script, Scala) e é fascinado pela complexidade - nem sempre aparente - que envolve datas e horas.

Já escreveu muito código para lidar com datas, e entre um bug e outro, aprendeu bastante a respeito disso. Código que só falha no horário de verão, ou que depende do fuso horário configurado no servidor, entre outras situações estranhas que só as datas e horas nos proporcionam, são ao mesmo tempo fontes de inspiração e raiva, de motivação para entender mais e indignação por serem tão desnecessariamente complicadas.

Pré-requisitos

A primeira parte deste livro é conceitual e não depende de nenhuma tecnologia específica, portanto não há nenhum conhecimento técnico prévio como pré-requisito. Para o restante, é necessário o mínimo de familiaridade com Java, para que os códigos possam ser entendidos. Assume-se que você saiba pelo menos o básico da linguagem.

Conforme já foi dito, se você não programa em Java, ainda assim poderá aproveitar um pouco da segunda e terceira partes do livro. Haverá bastante código, mas também terá algumas explicações conceituais, aprofundando ou reforçando o que foi visto na primeira parte.

A maior parte dos códigos deste livro foi testada com o JDK 1.8.0_131. Quando não houver uma indicação explícita da versão utilizada, deve-se assumir que foi esta. Há alguns códigos que foram testados nas versões 1.7.0_51 e 10.0.1. Se houver um exemplo específico que foi testado em alguma destas versões, isto será indicado no texto.

Sumário

    Parte 1: Conceitos fundamentais de data e hora
  • 1 Que dia é hoje? Que horas são?
    • 1.1 Data e hora local
  • 2 Fusos horários e os timezones
    • 2.1 E assim surgiu o GMT
    • 2.2 UTC, o novo GMT
    • 2.3 Como funciona o horário de verão
    • 2.4 Nada é garantido, nada é para sempre
  • 3 Nomenclatura dos timezones e formatos de data
    • 3.1 Abreviações de timezone e suas limitações
    • 3.2 Timezone e Offset não são a mesma coisa
    • 3.3 Datas não têm formato
    • 3.4 O formato ISO 8601
    • 3.5 Parsing e formatação
  • 4 O Unix Epoch e os timestamps
    • 4.1 Tenho uma data, como calcular o timestamp?
    • 4.2 Devo usar sempre timestamp/UTC?
    • 4.3 Nem sempre você precisa do timestamp
  • 5 Durações e a bizarra aritmética de datas
    • 5.1 Formato ISO 8601 para durações
    • 5.2 Somar um dia é o mesmo que somar 24 horas?
    • 5.3 Um mês tem quantos dias?
  • 6 E vamos ao código?

  • Parte 2: APIs legadas do Java
  • 7 A primeira API de data do Java
    • 7.1 java.util.Date não é uma data
    • 7.2 Construindo uma data específica
    • 7.3 Calendar, uma tentativa de melhorar Date
    • 7.4 Usando timezones com Calendar
    • 7.5 Calendar aceita qualquer valor
  • 8 Formatação usando SimpleDateFormat e Locale
    • 8.1 Formatação: converter data para texto
    • 8.2 Usar nomes em vez de números
    • 8.3 Formatar para ISO 8601
  • 9 Parsing com SimpleDateFormat
    • 9.1 Parsing: converter texto para data
    • 9.2 Cuidado com datas "incompletas"
    • 9.3 Parsing usando locales
    • 9.4 Parsing de UTC: não ignore o Z!
    • 9.5 Com SimpleDateFormat pode (quase) tudo
    • 9.6 Parsing de frações de segundo
    • 9.7 Usando SimpleDateFormat em ambientes multithread
  • 10 Aritmética de datas com Date e Calendar
    • 10.1 Como somar 2 horas a um Date?
    • 10.2 Prefira usar Calendar
    • 10.3 Calcular diferença entre datas
    • 10.4 Não confunda duração com data
  • 11 As classes de data do pacote java.sql
    • 11.1 java.sql.Date e Time não representam uma data e hora específicas
    • 11.2 java.sql.Timestamp, o único nome que faz sentido
  • 12 Timezones e outros casos de uso
    • 12.1 Obtendo informações do timezone
    • 12.2 Alguns casos práticos
    • 12.3 Sempre há um timezone em ação
    • 12.4 De onde o Java pega as informações de timezone
    • 12.5 Outros casos de uso

    Parte 3: A API java.time
  • 13 Princípios básicos do java.time
    • 13.1 Classes de data e hora local
    • 13.2 Obter a data e hora atual
    • 13.3 Manipulando as datas e horas
    • 13.4 Ajustes customizados com TemporalAdjuster
    • 13.5 Comparando as datas e horas
  • 14 Trabalhando com timezones e offsets
    • 14.1 Funcionamento básico de ZonedDateTime
    • 14.2 Como ZonedDateTime lida com gaps e overlaps
    • 14.3 Manipulando o ZonedDateTime
    • 14.4 Comparando instâncias de ZonedDateTime
    • 14.5 Converter para outro timezone
    • 14.6 Combinando as classes locais com ZoneId
    • 14.7 Trabalhando somente com offsets
  • 15 Instant e TemporalFields
    • 15.1 Instant representa um timestamp
    • 15.2 Criar um Instant a partir do timestamp
    • 15.3 TemporalField e os getters genéricos
    • 15.4 Mudando campos do Instant
    • 15.5 Usando TemporalField com TemporalQuery
  • 16 Aritmética de data e durações no java.time
    • 16.1 Somar e subtrair unidades de data e hora
    • 16.2 Somando qualquer unidade de tempo
    • 16.3 Classes específicas para durações
    • 16.4 Somar durações a uma data
    • 16.5 Calcular diferenças entre datas
  • 17 Formatação com java.time
    • 17.1 Usando pattern e locales
    • 17.2 Não precisa setar o timezone
    • 17.3 Formatar para ISO 8601
    • 17.4 Patterns opcionais
    • 17.5 Opções avançadas com DateTimeFormatterBuilder
  • 18 Parsing com java.time
    • 18.1 Devemos indicar o tipo a ser obtido
    • 18.2 Pattern opcional e valores predefinidos
    • 18.3 Locales, maiúsculas e textos customizados
    • 18.4 Validação e modos de parsing
    • 18.5 Parsing pode retornar mais de um tipo diferente
    • 18.6 Parsing de ISO 8601
    • 18.7 Parsing de abreviação de timezone
  • 19 Testes e outros casos de uso
    • 19.1 Funcionamento básico de java.time.Clock
    • 19.2 Manipulando o tempo
    • 19.3 Obtendo informações do timezone
    • 19.4 Criar um TemporalAdjuster
  • 20 Migração entre java.time e API legada
    • 20.1 Relação entre Date e as novas classes
    • 20.2 Conversões envolvendo Calendar
    • 20.3 Conversão entre TimeZone e ZoneId
    • 20.4 Classes do pacote java.sql
    • 20.5 Quando não converter entre as APIs
    • 20.6 Quando misturar as APIs?
    • 20.7 Diferenças entre SimpleDateFormat e DateTimeFormatter
    • 20.8 Considerações finais

Dados do produto

Número de páginas:
375
ISBN:
978-85-7254-005-6
Data publicação:
03/2019

Compartilhe!

Compartilhe no Facebook Compartilhe no Twitter