Introduction
Working with dates and time is one of the most common tasks in modern development. Whether it's event logging, deadline calculation, calendar display, or application internationalization, a Kotlin developer needs to know how to properly handle temporal data. In this article, we will thoroughly examine how to work with dates and time in Kotlin using the modern java.time API, which has been available since Java 8 and is fully compatible with Kotlin. You will learn about key classes, formatting, parsing, working with time zones, and practical examples that will help you write clean and reliable code.
Main classes for working with dates and time
In Kotlin, as in Java, the main work with dates and time is built on the java.time package. This package was created to replace the outdated java.util.Date and java.util.Calendar. It offers immutable and thread-safe classes. Let's look at the most important ones.
LocalDate — date without time
The LocalDate class represents a date (year, month, day) without time and time zone. It is ideal for birthdays, holidays, or event dates.
import java.time.LocalDate
fun main() { // Current date val today: LocalDate = LocalDate.now() println("Today: $today") // Output: 2025-04-11
// Specific date val specificDate: LocalDate = LocalDate.of(2025, 12, 25) println("Christmas: $specificDate")
// Adding days val nextWeek: LocalDate = today.plusDays(7) println("In a week: $nextWeek")}LocalTime — time without date
If you only need time (hours, minutes, seconds, nanoseconds), use LocalTime.
import java.time.LocalTime
fun main() { val now: LocalTime = LocalTime.now() println("Current time: $now")
val meetingTime: LocalTime = LocalTime.of(14, 30) println("Meeting at: $meetingTime")
val oneHourLater: LocalTime = now.plusHours(1) println("In an hour: $oneHourLater")}LocalDateTime — date and time together
This is a combination of LocalDate and LocalTime. It is the most popular class for storing a point in time without time zone binding.
import java.time.LocalDateTime
fun main() { val currentDateTime: LocalDateTime = LocalDateTime.now() println("Now: $currentDateTime")
val newYear: LocalDateTime = LocalDateTime.of(2026, 1, 1, 0, 0) println("New Year: $newYear")}ZonedDateTime and Instant — working with time zones
ZonedDateTime adds time zone information (ZoneId) to LocalDateTime. Instant represents a point in time in UTC (machine time).
import java.time.ZonedDateTimeimport java.time.ZoneIdimport java.time.Instant
fun main() { // Time in a specific time zone val moscowTime: ZonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow")) println("Time in Moscow: $moscowTime")
// Current moment in UTC val instant: Instant = Instant.now() println("UTC timestamp: $instant")}Formatting and parsing dates
To convert a date to a string (formatting) and a string to a date (parsing), the DateTimeFormatter class is used. It allows you to specify any patterns.
Formatting a date to a string
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("Formatted date: $formattedDate") // Output: 11.04.2025
// Other pattern examples val formatter2 = DateTimeFormat