Skip to content

Latest commit

 

History

History
174 lines (107 loc) · 10.3 KB

java time.md

File metadata and controls

174 lines (107 loc) · 10.3 KB
tags title
Java, Basic, Dates, java.time, 8
java.time (JDK 8)

Библиотека java.time

В 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

По факту 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 — интерфейс стратегии коррекции временной точки/метки, например перемещение в первый день текущего кода.

Хранение временных точек

Instant

Неизменяемый класс хранящий время с наносекундной точностью (внутри хранит количество секунд с 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

LocalTime — это кортеж (час, минуты, секунды, наносекунды) LocalDate — это кортеж (год, месяц, день месяца) LocalDateTime — оба кортежа вместе

К этим же классам я бы отнес еще и специфические классы для хранения части информации: MonthDay, Year, YearMonth.

Все эти классы объединяет то, что они содержат временные метки или их части, но временные точки на временной оси сами по себе определить не в состоянии (даже LocalDateTime) — поскольку ни в одном из них нет ни временной зоны, ни даже смещения.

Создание

  • Методами of указывая необходимые параметры (год, месяц и т.д.)
  • Методами now() и now(Clock)
  • Методом ofInstant(Instant, ZoneId) - ZoneId нужен так, как Instant не хранит её, а от неё будет зависеть время (хотя сами классы с префиксом Local зону не хранят)
  • from(TemporalAccesser) - создание из временного объекта, если это возможно
  • parse(CharSequence)

Изменение

К временным объектам можно прибавлять дни, месяцы и т.п. При этом сами объекты immutable.

Например с помощью методов plusDays(2).

ZonedDateTime

Включает всю информацию о времени, смещении, зоне и т.п.

Создаётся также, как и LocalDateTime, но с использованием зоны.

OffsetTime, OffsetDateTime

Вместо зоны хранит смещение.

Зона - история всех смещений за всё время, смещение - изменение часов на конкретный момоент.

Хранение временных промежутков

В новом 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);