Try English version of Quizful



Раздаем бесплатные Q! подробности в группе Quizful.Alpha-test
Партнеры
Рекрутерам: Прескрининг кандидатов about
Топ контрибуторов
loading
loading
Знаете ли Вы, что

В разделе "Статьи" можно найти обучающие статьи по информационным технологиям, а также узнать о новостях сервиса Quizful.

Лента обновлений
ссылка 15:38:56
Добавлен вопрос в тест C# - Средний уровень
ссылка 15:11:57
Добавлен вопрос в тест C# - Средний уровень
ссылка 15:03:58
Добавлен вопрос в тест C# - Средний уровень
ссылка 14:51:10
Комментарий от olegchap:
Совершенно правы. Опечатка. Спасибо за сигнал. Исправил...
ссылка 12:12:41
Комментарий от lenarikil:
"Вы как нибудь сами скомпилируйте, а то у меня лапки" ...
Статистика

Тестов: 153, вопросов: 8581. Пройдено: 393520 / 1913902.

Java 8 date api

head tail Статья
категория
Java
дата11.07.2014
авторAliakseiBoole
голосов18

Долгое время то, как реализована работа времени и даты в Java, было отличным поводом для шуток и издевок со стороны адептов других языков программирования. Вот только краткий список тех проблем, с которыми приходилось сталкиваться раньше:

  • Счёт времен не пойми что. К примеру, в java.util.Date дни начинаются с 0, а в java.uti.Calendar уже с 1, а первый день недели - воскресенье.
  • Отсутсвие простого и внятного API для рутинных операций по изменению времени.
  • Отсутсвие нормальной поддержки временных зон и других календарей, кроме Грегорианского.
  • Потоконебезопасность.
  • Отсутвие поддержки из коробки большого количества форматов дат.

Осознавая всю неудобность стандартного API со временем, комьюнити Java создали свое, которое было реализовано в такой популярной библиотеке как Joda-time.

И вот компания Oracle, одумавшись, создало новое API для работы с датами и временем. Чтобы не придумывать очередной велосипед, они пригласили к сотрудничеству Стивена Колборна, одного из разработчиков Joda-time.

Хватит истории, пора переходить к практике. Если вы до этого использовали Joda-time, то ничего особо нового не узнаете.

LocalDate, LocalTime и LocalDateTime

Основными объектами нового API стали классы LocalDate, LocalTime и LocalDateTime (последний является этаким объединением двух предыдущих). Официальная документация oracle советует представлять эти классы как календарь или часы на стене возле вас.

Для начала создадим пару объектов этих классов и посмотрим, что нам вернет их toString():


LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.now();

System.out.println(localTime); // 15:06:58.074
System.out.println(localDate); // 2014-06-30
System.out.println(localDateTime); // 2014-06-30T15:08:19.809

Судя по принтингу, нас не обманули, текстовое представление объектов действительно похоже на календарь или часы на столе. По мне это очень удобно.

Объект LocalDateTime можно получить слиянием первых двух объектов:


LocalDateTime fromLocalTime = localTime.atDate(localDate);
LocalDateTime fromDateTime = localDate.atTime(localTime);

System.out.println(fromDateTime);   // 2014-06-30T15:08:19.074
System.out.println(fromLocalTime);  // 2014-06-30T15:08:19.074

Также объект LocalDateTime можно получить из localDate добавлением времени в формате int:


fromDateTime = localDate.atTime(23,59,57,01);
System.out.println(fromDateTime);  //  2014-06-30T23:59:57.001

Теперь попробуем изменить формат вывода данных, чтобы день, месяц и год представлялись в привычной стилистике (30.04.2014):


DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("d.MM.YYYY");
System.out.println(dateTimeFormatter.format(localDate));  //  30.06.2014

try
{
System.out.println(dateTimeFormatter.format(localTime));
}
catch (UnsupportedTemporalTypeException e)
{
System.out.println("Wrong formatter.");
}

System.out.println(dateTimeFormatter.format(localDateTime)); //  30.06.2014

Как видно из кода, если мы попробуем отформатировать localTime, то будет выброшено исключение UnsupportedTemporalTypeException, так как это время дня, и оно ничего не знает о том, какой сейчас месяц, день и год. Более подробно о том, какие уже форматеры доступны из коробки, и какие паттерны можно использовать, вы всегда можете посмотреть в официальной документации [ЧИТАТЬ ТУТ ПРО DateTimeFormatter]. Поэтому не будем на этом долго останавливаться.

Настало время попробовать поизменять значения наших дат:


localTime = localTime.minusMinutes(60)
.plusHours(1)
.plusSeconds(60)
.minusMinutes(1);

localDate = localDate.minusYears(1)
.plusMonths(12)
.minusDays(365)
.plusYears(1);

localDateTime = localDateTime.minusMinutes(60)
.plusHours(1)
.minusMinutes(1)
.plusSeconds(60)
.plusMonths(12)
.minusYears(1)
.minusDays(365)
.plusYears(1);

System.out.println(localTime); // 15:06:58.074
System.out.println(localDate); // 2014-06-30
System.out.println(localDateTime); // 2014-06-30T15:08:19.809

Как видно из листинга, это делать стало легко, просто и понятно. И если вы внимательно смотрели на пример, то сразу обратили внимание, что я без всяких проблем смог прибавлять и отнимать разные значения, чтобы в конце получить ту же дату!

Обращаю ваше внимание на следующий факт: ОБЪЕКТЫ В НОВОМ API ЯВЛЯЮТСЯ IMMUTABLE (НЕИЗМЕНЯЕМЫМИ)! Поэтому не стоит слишком злоупотреблять вычислениями значений времени в циклах.

А теперь попробуем поработать с датами как нормальные люди! И вычислим, каким днём будет следующий понедельник:


localDate = localDate.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println(localDate); // 2014-07-07

Если заюзать такую замечательную возможность Java как static imports, то наш код превращается чуть ли не в предложение на чистом английском языке.


localDate = localDate.with(next(MONDAY));
System.out.println(localDate); // 2014-07-07

Instant

Объекты этого класса хранят миллисекунды с 01.01.1970 и являются местным эквивалентом старого доброго java.util.Date. Вот пару аналогий на тему, что с ним можно делать:


Instant instant = Instant.now();
System.out.println(instant); // 2014-06-30T13:37:27.703Z
System.out.println(instant.toEpochMilli()); // 1404135447703

instant = instant.plusSeconds(1).minusMillis(1000);
System.out.println(instant); // 2014-06-30T13:37:27.703Z

ZonedDateTime

Класс аналог GregorianCalendar необходим для работы с часовыми поясами. Очень удобная вещь! Я сам из Минска, поэтому давайте посчитаем время в Минске с учетом временной зоны, а затем рассчитаем, какое сейчас время в Москве, после чего преобразуем его в LocalDateTime:


ZoneId minskZone = ZoneId.of("Europe/Minsk");
ZoneId moscowZone = ZoneId.of("Europe/Moscow");

ZonedDateTime minskTime = ZonedDateTime.of(LocalDateTime.now(), minskZone);
System.out.println(minskTime);  // 2014-06-30T17:08:46.400+03:00[Europe/Minsk]

ZonedDateTime moscowTime = minskTime.withZoneSameInstant(moscowZone);
System.out.println(moscowTime);  // 2014-06-30T18:08:46.400+04:00[Europe/Moscow]
System.out.println(moscowTime.toLocalDateTime());  // 2014-06-30T18:09:54.544

Period

Вот ещё одна очень модная и клевая фишка нового API. Позволяет прозрачно и удобно отсчитывать время от какой-то точки. Например, расчитаем, сколько мне сейчас лет:


LocalDate today = LocalDate.now();
LocalDate MyBirthday = LocalDate.of(1988, Month.APRIL, 3);

Period period = Period.between(MyBirthday, today);
long myDays = ChronoUnit.DAYS.between(MyBirthday, today);
String result = String.format("You are %s years, %s months, and %s days old. (%s days total)",    period.getYears(),
                                                                                               period.getMonths(),
                                                                                               period.getDays(),
                                                                                               myDays);
System.out.println(result); // You are 26 years, 2 months, and 27 days old. (9584 days total)

Chronologies

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

  • Вы ведёте разработку для военных, есть необходимость вести отсчет, в оперативном времени.
  • Вы живёте в стране наподобие КНР и вам нужно производить перерасчет из даты ISO в дату календаря Чучхе.

API и JDBC

ANSI SQLJava SE 8
DATELocalDate
TIMELocalTime
TIMESTAMPLocalDateTime
TIME WITH TIMEZONEOffsetTime
TIMESTAMP WITH TIMEZONEOffsetDateTime

Таблица взята из официальной документации и показывает, к какому типу SQL может быть приведён объект нового временного пакета

Всё описанное в данной статье не является полным и подробным руководством, а лишь описывает основные возможности. Чтобы полностью осознать и научиться мастерски пользоватся новым API, нужно написать не одну программу и прочитать не один мануал и статью. Так что да пребудет с вами сила.

Если Вам понравилась статья, проголосуйте за нее

Голосов: 18  loading...
admin   Enshteinzh   moriarty   drito   Heorhi_Puhachou   kutyaharapos   SkunS   mikolasw   dra_Koshka   DanUrov   alexM   Diesel594   cantributor   sbfi   alek_yam   shiniktory   ckatt   spiritus