Статьи

Представляем новый API даты и времени для JDK 8

Обработка даты и времени в Java — довольно сложная часть, когда вы новичок в языке. Доступ ко времени можно получить через статический метод System.currentTimeMillis (), который возвращает текущее время в миллисекундах с 1 января 1970 года. Если вы предпочитаете работать с объектами, вместо этого вы можете использовать java.util.Date , класс, методы которого в большинстве своем устарели в последние версии Java. Для работы со смещением времени, скажем, добавьте один месяц к дате, есть java.util.GregorianCalendar . В общем, описанные здесь методы не очень удобны для работы. Java 7 и ниже не имеют хорошего API даты и времени. Библиотека Joda Time — это распространенное раскрытие, если вам нужно работать с датой / временем.

С JSR 310 (Запрос спецификации Java) это собирается измениться. JSR 310 добавляет новый API даты, времени и календаря в Java 8 . Проект ThreeTen предоставляет эталонную реализацию для этого нового API и уже может использоваться в текущих проектах Java (однако я рекомендую не делать этого для производства). Как README заявляет:

API в настоящее время считается пригодным для использования и точным, но неполным и может изменяться.
Если вы используете этот API, вы должны иметь возможность обрабатывать несовместимые изменения в более поздних версиях.

Здание ThreeTen

Построить проект ThreeTen относительно просто. Это требует, чтобы и Git, и Ant были установлены в вашей системе.

git clone git://github.com/ThreeTen/threeten.git
cd threeten
ant

Сначала будут получены самые последние версии ThreeTen, а затем начнется процесс сборки с использованием ant. Обратите внимание, что для сборки библиотеки также требуется либо OpenJDK 1.6, либо Oracle JDK 1.6.

JSR 310

Новый API определяет ряд новых классов, которые подразделяются на категории непрерывного и человеческого времени. Непрерывное время основано на времени Unix и представлено в виде единого возрастающего числа.

Учебный класс Описание
Мгновенное Момент времени в наносекундах с 1 января 1970 года
продолжительность Количество времени, измеренное в наносекундах

Человеческое время основано на областях, которые мы используем в нашей повседневной жизни, таких как день, час, минута и секунда. Он представлен группой классов, некоторые из которых мы обсудим в этой статье.

Учебный класс Описание
LocalDate дата, без времени суток, смещения или зоны
Местное время время суток, без даты, смещения или зоны
LocalDateTime дата и время без смещения или зоны
OffsetDate дата со смещением, например +02: 00, без времени дня или зоны
OffsetTime время суток со смещением, например +02: 00, без даты или зоны
OffsetDateTime дата и время со смещением, например +02: 00, без зоны
ZonedDateTime дата и время с часовым поясом и смещением
Год месяц год и месяц
День месяца месяц и день
Год / MonthOfDay / DayOfWeek / … классы для важных полей
DateTimeFields хранит карту пар поле-значение, которые могут быть недействительными
Календарная доступ к низкоуровневому API
период описательное количество времени, например, «2 месяца и 3 дня»

В дополнение к вышеупомянутым классам были реализованы три вспомогательных класса. Класс Clock переносит текущее время и дату, ZoneOffset — это смещение времени от UTC, а ZoneId определяет часовой пояс, такой как «Австралия / Брисбен».

Использование API

Получение текущего времени

Текущее время представлено классом Clock . Класс абстрактный, поэтому вы не можете создавать его экземпляры. Статический метод systemUTC () вернет текущее время, основываясь на системных часах, и установит UTC.

import javax.time.Clock;

Clock clock = Clock.systemUTC();

Для использования часового пояса по умолчанию в вашей системе также существует systemDefaultZone ().

Clock clock = Clock.systemDefaultZone();

Затем метод millis () можно использовать для доступа к текущему времени в миллисекундах с 1 января 1970 года. Это показывает, что класс Clock и все его подклассы обернуты вокруг System.currentTimeMillis ().

Clock clock = Clock.systemDefaultZone();
long time = clock.millis();

Работа с часовыми поясами

Для работы с часовыми поясами вам необходимо импортировать класс ZoneId. Класс предоставляет метод для получения системного часового пояса по умолчанию:

import javax.time.ZoneId;
import javax.time.Clock;

ZoneId zone = ZoneId.systemDefault();
Clock clock = Clock.system(zone);

Как видно выше, ZoneId можно затем использовать для получения экземпляра Clock с этим часовым поясом. Другие часовые пояса могут быть доступны по их имени, например:

ZoneId zone = ZoneId.of("Europe/Berlin");
Clock clock = Clock.system(zone);

Получение человеческой даты и времени

Работа со временем, представленным в одной длинной переменной, не то, что мы хотели. Мы хотим работать с объектами, которые представляют удобочитаемое время. Классы LocalDate, LocalTime и LocalDateTime делают именно это.

import javax.time.LocalDate;

// The now() method returns the current DateTime
LocalDate date = LocalDate.now();
System.out.printf("%s-%s-%s", 
    date.getYear(), date.getMonthValue(), date.getDayOfMonth()
);

Использование LocalDate для печати текущей даты

Делать расчеты с временем и датами

Одна из наиболее важных функций JSR-310 заключается в том, что вы можете выполнять вычисления с датой и временем. API делает это очень простым.

import javax.time.LocalTime;
import javax.time.Period;
import static javax.time.calendrical.LocalPeriodUnit.HOURS;

Period p = Period.of(5, HOURS);
LocalTime time = LocalTime.now();
LocalTime newTime;
newTime = time.plus(5, HOURS);
// or
newTime = time.plusHours(5);
// or
newTime = time.plus(p);

Три способа добавления 5 часов к текущему времени

Каждый класс, представляющий человеческое время, реализует интерфейс AdjustableDateTime . Интерфейсу требуется метод плюс и минус, который принимает значение и PeriodUnit в качестве аргумента.

Вывод

Эта статья дала (очень) краткое введение в новый API даты и времени, который будет поставляться с Java 8. API кажется очень последовательным и хорошо продуманным и предоставляет множество способов взаимодействия с датой и временем. После выпуска Java 8 API будет перемещен из пакета javax.time в java.time , поэтому не возникнет конфликта, если вы начнете использовать текущую реализацию.