tags | title |
---|---|
Java, Basic, Dates, java.time, 8 |
java.time (JDK 8) |
В JDK 8 появилось новое API для работы с датами и временем. Рекомендуется посмотреть заметки по работе с датами и статью на хабре. А также неплохая статья.
Хранение | Формат | Парсинг |
---|---|---|
Instant | DateTimeFormatter | DateTimeFormatter |
LocalDate | ||
LocalTime | ||
LocalDateTime | ||
ZonedDateTime |
Clock нужен для тестирования разных временных зон и прочего.
Класс ZoneId обозначает временную зону.
Получается экземпляр класса с помощью метода of(String id)
. В качестве id
можно передать регион ("Europe/Moscow"), смещение ("UTC+4", "+03:00:00") или сокращение (список можно получить в ZoneId.SHORT_IDS
).
ZoneId zid1 = ZoneId.of("Europe/Moscow");
По факту Clock это основание для работы всего нового API. Его можно сконфигурировать так, как нужно для работы (установить время и зону отличную от реальных). Настройка обычно используется для тестов.
Стандартный экземпляр java.time.Clock можно создать только фабричными статическими методами (сам класс абстрактный).
systemDefaultZone
— метод создает системные часы во временной зоне по-умолчанию.systemUTC
— метод создает системные часы во временной зоне UTC.system
— метод создает системные часы в указанной временной зоне.fixed
— метод создает часы константного времени, то есть часы не идут, а стоят на месте.offset
— метод создает прокси над указанными часами, который смещает время на указанную величину.tickSeconds
— метод создает системные часы в указанной временной зоне, значение которых округлено до целых секунд.tickMinutes
— метод создает системные часы в указанной временной зоне, значение которых округлено до целых минут.tick
— метод создает прокси над указанными часами, который округляет значения времени до указанного периода.withZone
— метод создает копию текущих часов в другой временной зоне.
Для тестирования можно создать свои часы с нужной логикой работы.
Здесь все используемые методы
Clock clock = Clock.systemDefaultZone();
System.out.println(clock.getZone()); //Europe/Moscow
System.out.println(clock.millis()); //1583496980128
System.out.println(clock.instant()); //2020-03-06T12:16:20.128Z
Все временные классы реализуют интерфейс TemporalAccessor. С помощью него можно получить доступ к отдельным полям класса с помощью его метода get(ChronoField)
и getLong(ChronoField)
.
Для более сложных алгоритмов запросов можно использовать методы интерфейса TemporalQuery.
Для манипуляций со временем есть интерфейс Temporal (позволяет прибавлять дни и так далее).
TemporalAdjuster — интерфейс стратегии коррекции временной точки/метки, например перемещение в первый день текущего кода.
Неизменяемый класс хранящий время с наносекундной точностью (внутри хранит количество секунд с 1 января 1970 (Unix-time)(long) и количество наносекунд(int)).
Ничего не знает о временных зонах (по идее и не должен).
Instant instant = Clock.systemDefaultZone().instant();
System.out.println(instant.getEpochSecond()); //1583497411
System.out.println(instant.getNano()); //804000000
System.out.println(instant); //2020-03-06T12:24:22.804Z
LocalTime — это кортеж (час, минуты, секунды, наносекунды) LocalDate — это кортеж (год, месяц, день месяца) LocalDateTime — оба кортежа вместе
К этим же классам я бы отнес еще и специфические классы для хранения части информации: MonthDay, Year, YearMonth.
Все эти классы объединяет то, что они содержат временные метки или их части, но временные точки на временной оси сами по себе определить не в состоянии (даже LocalDateTime) — поскольку ни в одном из них нет ни временной зоны, ни даже смещения.
- Методами
of
указывая необходимые параметры (год, месяц и т.д.) - Методами
now()
иnow(Clock)
- Методом
ofInstant(Instant, ZoneId)
- ZoneId нужен так, как Instant не хранит её, а от неё будет зависеть время (хотя сами классы с префиксом Local зону не хранят) from(TemporalAccesser)
- создание из временного объекта, если это возможноparse(CharSequence)
К временным объектам можно прибавлять дни, месяцы и т.п. При этом сами объекты immutable.
Например с помощью методов plusDays(2)
.
Включает всю информацию о времени, смещении, зоне и т.п.
Создаётся также, как и LocalDateTime, но с использованием зоны.
Вместо зоны хранит смещение.
Зона - история всех смещений за всё время, смещение - изменение часов на конкретный момоент.
В новом API есть два класса для определения длительности.
- Period — описание календарной длительности (периода) в виде кортежа (год, месяц, день).
- Duration — описание точной длительности в виде целого количества секунд и долей текущей секунды в виде наносекунд.
DateTimeFormatter — класс определяет настройки форматирования и парсинга.
У класса есть предопределённые константы-шаблоны, а также можно создать свой паттерн с помощью ofPattern()
.
Синтаксис паттерна. Также в JavaDoc есть список.
Locale ruLocale = new Locale("ru", "RU");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:dd z", ruLocale);
Для преобразования к строке нужно вызвать метод format(DateTimeFormatter)
у объекта хранящего время (LocalDate и т.п.).
Можно вызвать статический метод parse(CharSequence, [DateTimeFormatter])
у временных классов.
Также можно вызвать метод parse(CharSequence)
у DateTimeFormatter. Метод возвращает объект типа TemporalAccessor из которого можно получить объект вызвав статический метод of(TemporalAccessor)
у нужного объекта хранящего время.
==Важно учитывать, что вызов of()
может выкинуть исключение, если строка не содержит достаточно информации для создания объекта==
Locale ruLocale = new Locale("ru", "RU");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:dd z", ruLocale);
ZonedDateTime zdt1 = ZonedDateTime.of(2005, 10, 30, 0, 0, 0, 0, ZoneId.of("Europe/Moscow"));
String text = zdt1.format(formatter);
System.out.println(text); //2005/10/30 00:00:30 MSD
TemporalAccessor ta = formatter.parse(text); // java.time.format.Parsed
ZonedDateTime zdt2 = ZonedDateTime.from(ta);