Advanced Work with Dates and Time in Kotlin
In modern Kotlin development, working with dates and time goes far beyond simply displaying the current date. At an advanced level, it is necessary to consider time zones, perform complex calculations with periods, parse non-standard formats, and handle timestamps in distributed systems. In this article, we will look at the key libraries and techniques that will help you write reliable and efficient code for working with dates and time in Kotlin.
1. Choosing a Library: java.time vs kotlinx-datetime
Kotlin is fully compatible with Java, so you can use the powerful java.time API (JSR-310), which is the standard for new projects. However, for multiplatform projects (KMP), it is better to choose kotlinx-datetime from JetBrains.
java.time (JVM)
Main classes: 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("Meeting in Moscow: $zonedMeeting")}kotlinx-datetime (Multiplatform)
Add the dependency to 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("Today: $date")}2. Parsing and Formatting Dates
Correct parsing is the foundation of working with external data. Let's look at advanced techniques.
Parsing with Non-Standard Formats
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) { // try the next one } } 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}Localized Formatting
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. Complex Calculations with Duration and Period
Duration — for precise time intervals (hours, minutes, seconds), Period — for calendar periods (years, months, days).
Difference Between Dates Considering Business Logic
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