Новый принцип работы с датой и временем в Java 8

Большая часть сообщества разработчиков жаловалась на классы Date и Calendar. Причин было много, таких как трудный для понимания, сложный в использовании и не гибкий. Класс Date даже устарел, и в документации по Java предлагается использовать класс Calendar вместо класса Date . И, кроме того, сравнение дат содержит ошибки.

Java 8 date api changes

JAVA 8 (Lambda) выпустила новые API / классы даты и времени (JSR-310), также называемые ThreeTen, которые просто изменили то, что вы делали до настоящего времени. Ключевой частью этого является предоставление нового API, который значительно проще в использовании и менее подвержен ошибкам.

Это обеспечило некоторые чрезвычайно востребованные функции, такие как:

  • Все ключевые открытые классы являются неизменяемыми и поточно-ориентированными.
  • Определенная терминология и поведение, которые могут принять другие области в вычислительной технике.
Table of Contents

New classes to represent local date and timezone
New classes to represent timestamp and duration
Added utility classes over existing enums
Date adjusters introduced
Building dates will be easier
New class to simulate system/machine clock
Timezone handling related changes
Date formatting changes
References

Новые классы для замены класса Date

Новые классы, предназначенные для замены класса Date, — LocalDate , LocalTime и LocalDateTime .

LOCALDATE

Класс LocalDate представляет дату. Нет представления о времени или часовом поясе.

LocalDate localDate = LocalDate.now();
System.out.println(localDate.toString());                //2013-05-15
System.out.println(localDate.getDayOfWeek().toString()); //WEDNESDAY
System.out.println(localDate.getDayOfMonth());           //15
System.out.println(localDate.getDayOfYear());            //135
System.out.println(localDate.isLeapYear());              //false
System.out.println(localDate.plusDays(12).toString());   //2013-05-27

LocalTime

Класс LocalTime представляет время. Нет представления даты или часового пояса.

//LocalTime localTime = LocalTime.now();     //toString() in format 09:57:59.744
LocalTime localTime = LocalTime.of(12, 20);
System.out.println(localTime.toString());    //12:20
System.out.println(localTime.getHour());     //12
System.out.println(localTime.getMinute());   //20
System.out.println(localTime.getSecond());   //0
System.out.println(localTime.MIDNIGHT);      //00:00
System.out.println(localTime.NOON);          //12:00

LocalDateTime

Класс LocalDateTime представляет дату и время. Нет представления о часовом поясе.

LocalDateTime localDateTime = LocalDateTime.now(); 
System.out.println(localDateTime.toString());      //2013-05-15T10:01:14.911
System.out.println(localDateTime.getDayOfMonth()); //15
System.out.println(localDateTime.getHour());       //10
System.out.println(localDateTime.getNano());       //911000000

Если вы хотите использовать функциональность даты с информацией о зоне, тогда Lambda предоставит вам дополнительные 3 класса, аналогичные OffsetDate , то есть OffsetDate , OffsetTime и OffsetDateTime . Смещение часового пояса может быть представлено в форматах «+05: 30» или «Европа / Париж». Это делается с помощью другого класса, т.е. ZoneId .

OffsetDateTime offsetDateTime = OffsetDateTime.now();
System.out.println(offsetDateTime.toString());            	//2013-05-15T10:10:37.257+05:30

offsetDateTime = OffsetDateTime.now(ZoneId.of(quot;+05:30quot;));
System.out.println(offsetDateTime.toString());            	//2013-05-15T10:10:37.258+05:30

offsetDateTime = OffsetDateTime.now(ZoneId.of(quot;-06:30quot;));
System.out.println(offsetDateTime.toString());            	//2013-05-14T22:10:37.258-06:30

ZonedDateTime zonedDateTime = 
				ZonedDateTime.now(ZoneId.of(quot;Europe/Parisquot;));
System.out.println(zonedDateTime.toString());     			//2013-05-15T06:45:45.290+02:00[Europe/Paris]

Новые классы для представления отметки времени и продолжительности

Instant

Для представления конкретной метки времени в любой момент необходимо использовать класс Instant. Представляет момент времени с точностью до наносекунд. Операции с Instant включают сравнение с другим Instant и добавление или вычитание длительности.

Instant instant = Instant.now();
System.out.println(instant.toString());                                 //2013-05-15T05:20:08.145Z
System.out.println(instant.plus(Duration.ofMillis(5000)).toString());   //2013-05-15T05:20:13.145Z
System.out.println(instant.minus(Duration.ofMillis(5000)).toString());  //2013-05-15T05:20:03.145Z
System.out.println(instant.minusSeconds(10).toString());				//2013-05-15T05:19:58.145Z

Duration

Duration class — это совершенно новая концепция, впервые представленная на языке Java. Он представляет разницу во времени между двумя метками времени.

Duration duration = Duration.ofMillis(5000);
System.out.println(duration.toString());     //PT5S

duration = Duration.ofSeconds(60);
System.out.println(duration.toString());     //PT1M

duration = Duration.ofMinutes(10);
System.out.println(duration.toString());     //PT10M

duration = Duration.ofHours(2);
System.out.println(duration.toString());     //PT2H

duration = Duration.between(Instant.now(), Instant.now().plus(Duration.ofMinutes(10)));
System.out.println(duration.toString());  //PT10M

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

Period

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

Period period = Period.ofDays(6);
System.out.println(period.toString());    //P6D

period = Period.ofMonths(6);
System.out.println(period.toString());    //P6M

period = Period.between(LocalDate.now(), 
			LocalDate.now().plusDays(60));
System.out.println(period.toString());   //P1M29D

Добавлены служебные классы поверх существующих

Текущая платформа Java SE использует int-константы для месяцев, дней недели, am-pm и т. Д. Теперь добавлено множество дополнительных служебных классов, которые работают поверх этих перечислений. Например, класс DayOfWeek является оберткой дневных списков и может использоваться в соответствии с другими классами.

//day-of-week to represent, from 1 (Monday) to 7 (Sunday)
System.out.println(DayOfWeek.of(2));        			//TUESDAY 

DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.getValue());         			//5

LocalDate localDate = LocalDate.now();
System.out.println(localDate.with(DayOfWeek.MONDAY));  //2013-05-13  i.e. when was monday in current week ?

Другими такими классами являются Month , MonthDay , Year , YearMonth и многие другие.

Настройщики даты

Регуляторы даты — еще одно прекрасное и полезное дополнение к инструментам обработки дат. Он легко решает такие проблемы, как: Как вы находите последний день месяца? Или на следующий рабочий день? Или неделю во вторник?

Давайте посмотрим в коде.

LocalDate date = LocalDate.of(2013, Month.MAY, 15);						//Today
		
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(endOfMonth.toString()); 								//2013-05-31

LocalDate nextTue = date.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println(nextTue.toString());									//2013-05-21

Создание объектов даты

Создание объектов даты теперь может быть выполнено с использованием шаблона построителя. Шаблон строителя позволяет создать объект, который вы хотите построить, используя отдельные части. Это достигается с помощью методов с префиксом «at».

//Builder pattern used to make date object
 OffsetDateTime date1 = Year.of(2013)
						.atMonth(Month.MAY).atDay(15)
						.atTime(0, 0)
						.atOffset(ZoneOffset.of(quot;+03:00quot;));
 System.out.println(date1);   									//2013-05-15T00:00+03:00

//factory method used to make date object
OffsetDateTime date2 = OffsetDateTime.
						of(2013, 5, 15, 0, 0, 0, 0, ZoneOffset.of(quot;+03:00quot;));
System.out.println(date2);										//2013-05-15T00:00+03:00

Для имитации системных/машинных часов

Новый класс Clock предлагается в новом выпуске. Моделирует функциональность системных часов. Разработчики любили эту функцию больше всего других. Причина в том, что во время юнит-тестирования вы часто обязаны тестировать API в будущем. Для этого мы перенаправили системные часы на следующую дату, а затем снова перезапустили сервер и протестировали приложение.

Теперь не нужно этого делать. Используйте класс Clock чтобы смоделировать этот сценарий.

Clock clock = Clock.systemDefaultZone();
System.out.println(clock);						//SystemClock[Asia/Calcutta]
System.out.println(clock.instant().toString());	//2013-05-15T06:36:33.837Z
System.out.println(clock.getZone());			//Asia/Calcutta

Clock anotherClock = Clock.system(ZoneId.of(quot;Europe/Tiraspolquot;));
System.out.println(anotherClock);						//SystemClock[Europe/Tiraspol]
System.out.println(anotherClock.instant().toString());	//2013-05-15T06:36:33.857Z
System.out.println(anotherClock.getZone());				//Europe/Tiraspol

Clock forwardedClock  = Clock.tick(anotherClock, Duration.ofSeconds(600));
System.out.println(forwardedClock.instant().toString());  //2013-05-15T06:30Z

Изменения часового пояса

Обработка часового пояса выполняется тремя основными классами. Это ZoneOffset, TimeZone, ZoneRules.

  • Класс ZoneOffset представляет фиксированное смещение от UTC в секундах. Обычно это представляется в виде строки формата «± чч: мм».
  • Класс TimeZone представляет идентификатор для региона, в котором определены указанные правила часового пояса.
  • ZoneRules — это фактический набор правил, которые определяют, когда изменяется смещение зоны.
//Zone rules
System.out.println(ZoneRules.of(ZoneOffset.of(quot;+02:00quot;)).isDaylightSavings(Instant.now()));
System.out.println(ZoneRules.of(ZoneOffset.of(quot;+02:00quot;)).isFixedOffset());

Форматирование даты

Форматирование даты поддерживается двумя классами, в основном, DateTimeFormatterBuilder и DateTimeFormatter . DateTimeFormatterBuilder работает с шаблоном компоновщика для создания пользовательских шаблонов, где DateTimeFormatter предоставляет необходимые входные данные для этого.

DateTimeFormatterBuilder formatterBuilder = new DateTimeFormatterBuilder();
formatterBuilder.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
				.appendLiteral(quot;-quot;)
				.appendZoneOrOffsetId();
DateTimeFormatter formatter = formatterBuilder.toFormatter();
System.out.println(formatter.format(ZonedDateTime.now()));

Оцените статью