Trabalho Avançado com Datas e Horas em Kotlin
No desenvolvimento moderno com Kotlin, o trabalho com datas e horas vai muito além da simples exibição da data atual. Em um nível avançado, é necessário considerar fusos horários, realizar cálculos complexos com períodos, fazer parsing de formatos não padronizados e processar timestamps em sistemas distribuídos. Neste artigo, abordaremos as principais bibliotecas e técnicas que ajudarão você a escrever código confiável e eficiente para trabalhar com datas e horas em Kotlin.
1. Escolha da biblioteca: java.time vs kotlinx-datetime
Kotlin é totalmente compatível com Java, portanto você pode usar a poderosa API java.time (JSR-310), que é o padrão para novos projetos. No entanto, para projetos multiplataforma (KMP), é melhor escolher kotlinx-datetime da JetBrains.
java.time (JVM)
Classes principais: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant, Duration, Period.
import java.time.*
fun main() { val today = LocalDate.now() val meetingTime = LocalDateTime.of(2025, 3, 15, 14, 30) val zonedMeeting = ZonedDateTime.of(meetingTime, ZoneId.of("Europe/Moscow")) println("Reunião em Moscou: $zonedMeeting")}kotlinx-datetime (Multiplataforma)
Adicione a dependência no build.gradle.kts:
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")import kotlinx.datetime.*
fun main() { val now = Clock.System.now() val date = now.toLocalDateTime(TimeZone.of("Europe/Moscow")).date println("Hoje: $date")}2. Parsing e formatação de datas
O parsing correto é a base para trabalhar com dados externos. Vamos explorar técnicas avançadas.
Parsing com formatos não padronizados
import java.time.LocalDateTimeimport java.time.format.DateTimeFormatterimport java.time.format.DateTimeParseException
fun parseCustomDate(dateString: String): LocalDateTime? { val formatters = listOf( DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), DateTimeFormatter.ofPattern("dd/MM/yyyy'T'HH:mm"), DateTimeFormatter.ISO_LOCAL_DATE_TIME ) for (formatter in formatters) { try { return LocalDateTime.parse(dateString, formatter) } catch (e: DateTimeParseException) { // tentar o próximo } } return null}
fun main() { println(parseCustomDate("2025-03-15 14:30:00")) // 2025-03-15T14:30 println(parseCustomDate("15/03/2025T14:30")) // 2025-03-15T14:30}Formatação localizada
import java.time.LocalDateimport java.time.format.DateTimeFormatterimport java.time.format.FormatStyleimport java.util.Locale
fun main() { val date = LocalDate.of(2025, 3, 15) val usFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) .withLocale(Locale.US) val brFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) .withLocale(Locale("pt", "BR")) println("USA: ${date.format(usFormatter)}") // Saturday, March 15, 2025 println("BR: ${date.format(brFormatter)}") // sábado, 15 de março de 2025}3. Cálculos complexos com Duration e Period
Duration — para intervalos de tempo precisos (horas, minutos, segundos), Period — para períodos de calendário (anos, meses, dias).
Diferença entre datas considerando lógica de negócios
import java.time.*import java.time.temporal.ChronoUnit
fun businessDaysBetween(start: LocalDate, end: LocalDate): Long { var count = 0L var current = start while (current.isBefore(end)) { if (current.dayOfWeek != DayOfWeek.SATURDAY && current.dayOfWeek != DayOfWe