Trabajo avanzado con fechas y horas en Kotlin
En el desarrollo moderno con Kotlin, trabajar con fechas y horas va mucho más allá de simplemente mostrar la fecha actual. A nivel avanzado, se requiere considerar las zonas horarias, realizar cálculos complejos con períodos, analizar formatos no estándar y procesar marcas de tiempo en sistemas distribuidos. En este artículo, exploraremos las bibliotecas y técnicas clave que le ayudarán a escribir código robusto y eficiente para trabajar con fechas y horas en Kotlin.
1. Elección de biblioteca: java.time vs kotlinx-datetime
Kotlin es totalmente compatible con Java, por lo que puede usar la potente API java.time (JSR-310), que es el estándar para proyectos nuevos. Sin embargo, para proyectos multiplataforma (KMP), es mejor elegir kotlinx-datetime de JetBrains.
java.time (JVM)
Clases principales: 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ón en Moscú: $zonedMeeting")}kotlinx-datetime (Multiplataforma)
Agregue la dependencia en 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("Hoy: $date")}2. Análisis y formato de fechas
El análisis correcto es la base para trabajar con datos externos. Veamos técnicas avanzadas.
Análisis con formatos no estándar
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) { // probamos el siguiente } } 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}Formato localizado
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 ruFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) .withLocale(Locale("ru")) println("USA: ${date.format(usFormatter)}") // Saturday, March 15, 2025 println("RU: ${date.format(ruFormatter)}") // суббота, 15 марта 2025 г.}3. Cálculos complejos con Duration y Period
Duration — para intervalos de tiempo precisos (horas, minutos, segundos), Period — para períodos calendario (años, meses, días).
Diferencia entre fechas considerando lógica de negocio
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