Введение в работу с датами и временем в Kotlin
Работа с датами и временем — одна из самых частых задач в современной разработке. Будь то логирование событий, расчет сроков, планирование задач или отображение пользовательского интерфейса — без грамотной работы с временными метками не обойтись. В Kotlin, который полностью совместим с Java, стандартом де-факто является пакет java.time, представленный в Java 8. Этот пакет заменил устаревшие java.util.Date и java.util.Calendar, предложив потокобезопасный, иммутабельный и интуитивно понятный API.
В этой статье мы разберем все ключевые аспекты работы с датами и временем в Kotlin: от создания объектов до их форматирования, парсинга и выполнения арифметических операций. Вы узнаете, как использовать LocalDate, LocalTime, LocalDateTime, Instant, Duration и Period на практических примерах.
1. Основные классы для работы с датами и временем
Пакет java.time содержит несколько ключевых классов, каждый из которых решает свою задачу. Рассмотрим их подробнее.
1.1 LocalDate — работа с датой без времени
Класс LocalDate представляет дату (год, месяц, день) без учета времени и часового пояса. Идеально подходит для дней рождения, календарных событий и дат без привязки к конкретному моменту.
import java.time.LocalDate
fun main() {
// Текущая дата
val today = LocalDate.now()
println("Сегодня: $today") // 2025-04-05
// Конкретная дата
val newYear = LocalDate.of(2025, 1, 1)
println("Новый год: $newYear")
// Парсинг из строки
val parsedDate = LocalDate.parse("2025-12-31")
println("Парс даты: $parsedDate")
}
1.2 LocalTime — работа со временем без даты
LocalTime хранит только время (часы, минуты, секунды, наносекунды). Он полезен для хранения времени начала рабочего дня, расписания или таймеров.
import java.time.LocalTime
fun main() {
// Текущее время
val now = LocalTime.now()
println("Сейчас: $now")
// Конкретное время
val meetingTime = LocalTime.of(14, 30, 0)
println("Время встречи: $meetingTime")
// Парсинг
val parsedTime = LocalTime.parse("09:15:30")
println("Парс времени: $parsedTime")
}
1.3 LocalDateTime — объединение даты и времени
LocalDateTime объединяет LocalDate и LocalTime. Это наиболее часто используемый класс для хранения момента времени без часового пояса.
import java.time.LocalDateTime
fun main() {
// Текущие дата и время
val current = LocalDateTime.now()
println("Сейчас: $current")
// Создание из компонентов
val specific = LocalDateTime.of(2025, 4, 5, 10, 30, 0)
println("Конкретный момент: $specific")
// Комбинация даты и времени
val date = LocalDate.of(2025, 12, 25)
val time = LocalTime.of(18, 0)
val christmas = LocalDateTime.of(date, time)
println("Рождество: $christmas")
}
1.4 Instant — момент времени в UTC
Instant представляет точку на временной шкале в формате Unix timestamp (количество секунд и наносекунд с 1 января 1970 года). Незаменим для хранения логов, работы с базами данных и обмена данными между системами.
import java.time.Instant
fun main() {
// Текущий момент в UTC
val now = Instant.now()
println("Сейчас (UTC): $now")
// Из Unix timestamp
val fromEpoch = Instant.ofEpochSecond(1_700_000_000)
println("Из timestamp: $fromEpoch")
// Конвертация в миллисекунды
val millis = now.toEpochMilli()
println("Миллисекунды: $millis")
}
2. Форматирование и парсинг дат и времени
Для преобразования дат в строки и обратно используется класс DateTimeFormatter. Он поддерживает как стандартные, так и пользовательские шаблоны.
2.1 Форматирование дат
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun main() {
val now = LocalDateTime.now()
// Стандартные форматы
val isoFormat = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
println("ISO: $isoFormat")
// Пользовательский формат
val customFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")
val formatted = now.format(customFormatter)
println("Формат: $formatted")
// Другой пример
val dateFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy")
println("Читаемый: ${now.format(dateFormatter)}")
}
2.2 Парсинг строк в даты
import java.time.LocalDate
import java.time.format.DateTimeFormatter
fun main() {
val dateString = "05.04.2025"
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val date = LocalDate.parse(dateString, formatter)
println("Распарсено: $date")
// Обработка ошибок
try {
val badDate = LocalDate.parse("2025/04/05")
} catch (e: Exception) {
println("Ошибка парсинга: ${e.message}")
}
}
3. Манипуляции с датами и временем
Kotlin позволяет легко прибавлять и вычитать дни, месяцы, годы, а также находить разницу между датами.
3.1 Прибавление и вычитание
import java.time.LocalDate
import java.time.LocalDateTime
fun main() {
val today = LocalDate.now()
// Прибавление дней
val nextWeek = today.plusDays(7)
println("Через неделю: $nextWeek")
// Вычитание месяцев
val twoMonthsAgo = today.minusMonths(2)
println("2 месяца назад: $twoMonthsAgo")
// Работа с LocalDateTime
val now = LocalDateTime.now()
val nextHour = now.plusHours(1).plusMinutes(30)
println("Через 1.5 часа: $nextHour")
}
3.2 Разница между датами
Для измерения разницы во времени используются класс