Trabalho Avançado com Datas e Horas em Kotlin
\n\nNo desenvolvimento moderno com Kotlin, o tratamento adequado de datas e horas não é apenas uma conveniência, mas uma necessidade. Em um nível avançado, o desenvolvedor precisa lidar com fusos horários, períodos, durações e operações complexas de formatação. Neste artigo, exploraremos as principais ferramentas e técnicas que o ajudarão a escrever código confiável e eficiente.
\n\n1. Classes principais: LocalDate, LocalTime, LocalDateTime e Instant
\n\nKotlin herda completamente a poderosa biblioteca java.time (JSR-310), que se tornou o padrão para trabalhar com datas e horas no Java 8 e superior. Para Kotlin Multiplatform, existe a biblioteca kotlinx-datetime, mas em projetos JVM, a java.time continua sendo a mais popular.
LocalDate, LocalTime, LocalDateTime
\nEssas classes representam data e hora sem vinculação a um fuso horário. São ideais para armazenar aniversários, horários e outros dados onde o fuso horário não é importante.
\n\nimport java.time.LocalDate\nimport java.time.LocalTime\nimport java.time.LocalDateTime\n\nfun main() {\n val date = LocalDate.now()\n val time = LocalTime.of(14, 30, 0)\n val dateTime = LocalDateTime.of(date, time)\n \n println("Data: $date")\n println("Hora: $time")\n println("Data e hora: $dateTime")\n \n // Adição e subtração de dias\n val tomorrow = date.plusDays(1)\n println("Amanhã: $tomorrow")\n}\n\nInstant — carimbo de data/hora para máquinas
\nInstant representa um ponto na linha do tempo em UTC. É indispensável para logging, troca de dados entre servidores e trabalho com APIs.
import java.time.Instant\n\nfun main() {\n val now = Instant.now()\n println("Momento atual em UTC: $now")\n \n // Conversão de milissegundos\n val fromEpoch = Instant.ofEpochMilli(1_700_000_000_000)\n println("De milissegundos: $fromEpoch")\n}\n\n2. Fusos horários: ZonedDateTime e OffsetDateTime
\n\nQuando o aplicativo trabalha com usuários de diferentes regiões, é necessário considerar os fusos horários. Para isso, existem ZonedDateTime (com informações completas de zona) e OffsetDateTime (apenas deslocamento do UTC).
import java.time.ZonedDateTime\nimport java.time.ZoneId\nimport java.time.ZoneOffset\n\nfun main() {\n // Hora atual em Nova York\n val newYork = ZonedDateTime.now(ZoneId.of("America/New_York"))\n println("Nova York: $newYork")\n \n // Conversão do UTC\n val utcNow = ZonedDateTime.now(ZoneOffset.UTC)\n val moscowTime = utcNow.withZoneSameInstant(ZoneId.of("Europe/Moscow"))\n println("Moscou: $moscowTime")\n \n // OffsetDateTime para deslocamentos simples\n val offsetTime = java.time.OffsetDateTime.now(ZoneOffset.ofHours(3))\n println("+3 horas: $offsetTime")\n}\n\nImportante: Para a interface do usuário, sempre use ZonedDateTime para lidar corretamente com o horário de verão/inverno. OffsetDateTime é adequado para deslocamentos fixos, por exemplo, ao trabalhar com logs.
3. Diferença entre datas: Period e Duration
\n\nPara calcular a diferença de tempo, o Kotlin fornece duas classes: Period (para datas, em dias/meses/anos) e Duration (para intervalos precisos em segundos/nanossegundos).
Period — trabalho com unidades de calendário
\nimport java.time.LocalDate\nimport java.time.Period\n\nfun main() {\n val birthDate = LocalDate.of(1990, 5, 15)\n val today = LocalDate.now()\n val age = Period.between(birthDate, today)\n \n println("Idade: ${age.years} anos, ${age.months} meses, ${age.days} dias")\n \n // Adicionando período a uma data\n val nextMonth = today.plus(Period.ofMonths(1))\n println("Daqui a um mês: $nextMonth")\n}\n\n