Introducción
Trabajar con fechas y horas es una de las tareas más frecuentes en el desarrollo moderno. Ya sea para registro de eventos, cálculo de plazos, visualización de calendarios o internacionalización de aplicaciones, el desarrollador de Kotlin necesita saber cómo procesar correctamente los datos temporales. En este artículo, analizaremos en detalle cómo trabajar con fechas y horas en Kotlin, utilizando la API moderna java.time, que está disponible desde Java 8 y es totalmente compatible con Kotlin. Conocerás las clases clave, el formateo, el análisis sintáctico (parsing), el trabajo con zonas horarias y ejemplos prácticos que te ayudarán a escribir código limpio y confiable.
Clases principales para trabajar con fechas y horas
En Kotlin, al igual que en Java, el trabajo principal con fechas y horas se basa en el paquete java.time. Este paquete fue creado para reemplazar los obsoletos java.util.Date y java.util.Calendar. Ofrece clases inmutables (immutable) y seguras para hilos. Veamos las más importantes.
LocalDate — fecha sin hora
La clase LocalDate representa una fecha (año, mes, día) sin considerar la hora ni la zona horaria. Es ideal para cumpleaños, días festivos o fechas de eventos.
import java.time.LocalDate
fun main() { // Fecha actual val today: LocalDate = LocalDate.now() println("Hoy: $today") // Salida: 2025-04-11
// Fecha específica val specificDate: LocalDate = LocalDate.of(2025, 12, 25) println("Navidad: $specificDate")
// Adición de días val nextWeek: LocalDate = today.plusDays(7) println("En una semana: $nextWeek")}LocalTime — hora sin fecha
Si solo necesitas la hora (horas, minutos, segundos, nanosegundos), usa LocalTime.
import java.time.LocalTime
fun main() { val now: LocalTime = LocalTime.now() println("Hora actual: $now")
val meetingTime: LocalTime = LocalTime.of(14, 30) println("Reunión a las: $meetingTime")
val oneHourLater: LocalTime = now.plusHours(1) println("En una hora: $oneHourLater")}LocalDateTime — fecha y hora juntas
Es una combinación de LocalDate y LocalTime. Es la clase más popular para almacenar un momento en el tiempo sin vincularlo a una zona horaria.
import java.time.LocalDateTime
fun main() { val currentDateTime: LocalDateTime = LocalDateTime.now() println("Ahora: $currentDateTime")
val newYear: LocalDateTime = LocalDateTime.of(2026, 1, 1, 0, 0) println("Año Nuevo: $newYear")}ZonedDateTime e Instant — trabajo con zonas horarias
ZonedDateTime agrega a LocalDateTime la información de la zona horaria (ZoneId). Instant representa un momento en el tiempo en UTC (tiempo de máquina).
import java.time.ZonedDateTimeimport java.time.ZoneIdimport java.time.Instant
fun main() { // Hora en una zona horaria específica val moscowTime: ZonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow")) println("Hora en Moscú: $moscowTime")
// Momento actual en UTC val instant: Instant = Instant.now() println("Marca de tiempo UTC: $instant")}Formateo y análisis sintáctico (parsing) de fechas
Para convertir una fecha en una cadena (formateo) y una cadena en una fecha (análisis sintáctico) se utiliza la clase DateTimeFormatter. Permite definir cualquier patrón.
Formateo de fecha a cadena
import java.time.LocalDateimport java.time.format.DateTimeFormatter
fun main() { val date = LocalDate.now() val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy") val formattedDate: String = date.format(formatter) println("Fecha formateada: $formattedDate") // Salida: 11.04.2025
// Otros ejemplos de patrones val formatter2 = DateTimeFormat