Введение в работу с датами и временем в Kotlin
Работа с датами и временем — одна из ключевых задач в разработке любого приложения. Будь то логирование событий, расчёт сроков, отображение календаря или работа с временными метками — без надёжного инструментария не обойтись. В экосистеме Kotlin для этих целей используется мощная библиотека java.time, которая пришла на смену устаревшим java.util.Date и java.util.Calendar. Благодаря полной совместимости с Java, Kotlin позволяет использовать все возможности java.time напрямую, а также добавляет удобные расширения и синтаксический сахар.
В этой статье мы подробно разберём, как создавать, форматировать, парсить и преобразовывать даты и время в Kotlin. Вы узнаете о ключевых классах, таких как LocalDate, LocalTime, LocalDateTime, ZonedDateTime и Instant, а также научитесь работать с периодами и длительностями. Все примеры кода написаны на чистом Kotlin и готовы к использованию.
Основные классы для работы с датами и временем
Библиотека java.time предлагает несколько ключевых классов, каждый из которых решает свою задачу. Рассмотрим их подробнее.
LocalDate — работа с датой без времени
Класс LocalDate представляет дату (год, месяц, день) без учёта времени и часового пояса. Идеально подходит для дней рождения, календарных событий и задач, где время не имеет значения.
import java.time.LocalDate
fun main() {
// Текущая дата
val today = LocalDate.now()
println("Сегодня: $today")
// Конкретная дата
val specificDate = LocalDate.of(2024, 12, 25)
println("Рождество: $specificDate")
// Парсинг из строки
val parsedDate = LocalDate.parse("2024-12-25")
println("Распарсено: $parsedDate")
}
LocalTime — работа со временем без даты
LocalTime хранит только время (часы, минуты, секунды, наносекунды). Используется для расписаний, таймеров и временных меток без привязки к дате.
import java.time.LocalTime
fun main() {
// Текущее время
val now = LocalTime.now()
println("Сейчас: $now")
// Конкретное время
val lunchTime = LocalTime.of(13, 30)
println("Обед в: $lunchTime")
// Парсинг
val parsedTime = LocalTime.parse("15:45:30")
println("Распарсено: $parsedTime")
}
LocalDateTime — объединение даты и времени
LocalDateTime объединяет LocalDate и LocalTime. Это самый часто используемый класс для хранения момента времени без учёта часового пояса.
import java.time.LocalDateTime
import java.time.LocalDate
import java.time.LocalTime
fun main() {
// Текущий момент
val now = LocalDateTime.now()
println("Сейчас: $now")
// Из отдельных компонентов
val date = LocalDate.of(2024, 12, 25)
val time = LocalTime.of(10, 0)
val christmasMorning = LocalDateTime.of(date, time)
println("Рождественское утро: $christmasMorning")
// Комбинированный метод
val newYear = LocalDateTime.of(2025, 1, 1, 0, 0)
println("Новый год: $newYear")
}
Форматирование и парсинг дат
Для преобразования дат в строки и обратно используется класс DateTimeFormatter. Он поддерживает множество предопределённых форматов, а также позволяет создавать собственные шаблоны.
Форматирование даты в строку
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun main() {
val now = LocalDateTime.now()
// Стандартный формат ISO
val isoFormat = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
println("ISO: $isoFormat")
// Пользовательский формат
val customFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")
val customFormat = now.format(customFormatter)
println("Пользовательский: $customFormat")
// Только дата
val dateFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy")
println("Дата: ${now.format(dateFormatter)}")
}
Парсинг строки в дату
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun main() {
val dateString = "25.12.2024"
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val date = LocalDate.parse(dateString, formatter)
println("Распарсено: $date")
val dateTimeString = "2024-12-25 15:30:00"
val dtFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val dateTime = LocalDateTime.parse(dateTimeString, dtFormatter)
println("Распарсено: $dateTime")
}
Работа с часовыми поясами и временными метками
Когда ваше приложение работает с пользователями из разных часовых поясов, на помощь приходят классы ZonedDateTime и Instant.
ZonedDateTime — дата и время с часовым поясом
ZonedDateTime содержит полную информацию о дате, времени и часовом поясе. Это незаменимо для международных приложений.
import java.time.ZonedDateTime
import java.time.ZoneId
fun main() {
// Текущий момент в UTC
val utcNow = ZonedDateTime.now(ZoneId.of("UTC"))
println("UTC: $utcNow")
// Конкретный часовой пояс
val moscowNow = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
println("Москва: $moscowNow")
// Преобразование между поясами
val nyNow = moscowNow.withZoneSameInstant(ZoneId.of("America/New_York"))
println("Нью-Йорк: $nyNow")
}
Instant — машинное время
Instant представляет момент времени в наносекундной точности относительно эпохи Unix (1 января 1970 года UTC). Используется для хранения временных меток в базах данных и логирования.
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
fun main() {
// Текущий момент
val now = Instant.now()
println("Instant: $now")
// Из миллисекунд
val fromEpoch = Instant.ofEpochMilli(170000000000