Вопрос-ответ

What's the difference between Instant and LocalDateTime?

В чем разница между Instant и LocalDateTime?

Я знаю, что:


  • Instant - это скорее "техническое" представление временной метки (наносекунды) для вычислений.

  • LocalDateTime - это скорее представление даты / часов включая часовые пояса для людей.

Тем не менее, в конце концов, IMO оба могут быть приняты за типы для большинства вариантов использования приложений. В качестве примера: в настоящее время я запускаю пакетное задание, в котором мне нужно рассчитать следующий запуск на основе дат, и я изо всех сил пытаюсь найти плюсы / минусы между этими двумя типами (кроме преимущества в наносекундной точности Instant и части часового пояса LocalDateTime).

Можете ли вы назвать несколько примеров приложений, в которых следует использовать только Instant или LocalDateTime?

Редактировать: Остерегайтесь неверно прочитанной документации для LocalDateTime относительно точности и часового пояса.

Переведено автоматически
Ответ 1

Таблица всех типов даты и времени в Java, как современных, так и устаревших

tl; dr

Instant и LocalDateTime - это два совершенно разных животных: одно представляет момент, другое - нет.


  • Instant представляет момент, определенную точку на временной шкале.

  • LocalDateTime представляет дату и время суток. Но из-за отсутствия часового пояса или смещения от UTC, этот класс не может представлять момент. Он представляет потенциальные моменты в диапазоне примерно от 26 до 27 часов, диапазон всех часовых поясов по всему миру. LocalDateTimeЗначение по своей сути неоднозначно.

Неверное предположение


LocalDateTime это скорее представление даты / часов, включая часовые пояса для людей.


Ваше утверждение неверно: у LocalDateTimeA нет часового пояса. Весь смысл этого класса в отсутствии часового пояса.

Чтобы процитировать этот класс ’ doc:


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


So Local… означает “не зонировано, без смещения”.

Instant

введите описание изображения здесь

An Instant - это момент на временной шкале в UTC, отсчет в наносекунды с эпохи первого момента 1970 UTC (в принципе, подробные сведения см. в документе class doc). Поскольку большая часть вашей бизнес-логики, хранения данных и обмена данными должны выполняться в UTC, это удобный класс для частого использования.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

OffsetDateTime

введите описание изображения здесь

Класс OffsetDateTime class представляет момент в виде даты и времени с контекстом на некоторое количество часов-минут-секунд раньше или позже UTC. Величина смещения, количество часов-минут-секунд, представлена классом ZoneOffset.

Если количество часов-минут-секунд равно нулю, an OffsetDateTime представляет момент в UTC так же, как и an Instant.

ZoneOffset

введите описание изображения здесь

ZoneOffset Класс представляет смещение от UTC, на несколько часов-минут-секунд опережающее UTC или отставающее от UTC.

A ZoneOffset - это просто количество часов-минут-секунд, не более. Зона - это гораздо больше, у нее есть имя и история изменений для смещения. Таким образом, использование зоны всегда предпочтительнее простого смещения.

ZoneId

введите описание изображения здесь

Часовой пояс представлен ZoneId классом.

Например, в Париже новый день наступает раньше, чем в Монреале. Итак, нам нужно переместить стрелки часов, чтобы они лучше отражали полдень (когда Солнце находится прямо над головой) для данного региона. Чем дальше на восток / запад от линии UTC в Западной Европе / Африке, тем больше смещение.

Часовой пояс - это набор правил для обработки корректировок и аномалий, практикуемых местным сообществом или регионом. Наиболее распространенной аномалией является слишком популярное безумие, известное как переход на летнее время (DST).

У часового пояса есть история прошлых правил, текущих правил и подтвержденных правил на ближайшее будущее.

Эти правила меняются чаще, чем вы могли бы ожидать. Обязательно поддерживайте в актуальном состоянии правила вашей библиотеки даты и времени, обычно являющейся копией базы данных 'tz'. Поддерживать актуальность в Java 8 стало проще, чем когда-либо, благодаря Oracle, выпустившей инструмент обновления часовых поясов.

Укажите правильное название часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте аббревиатуры из 2-4 букв, такие как EST или IST, поскольку они не являются не настоящими часовыми поясами, не стандартизированы и даже не уникальны (!).


Часовой пояс = Смещение + Правила корректировки


ZoneId z = ZoneId.of( “Africa/Tunis” ) ; 

ZonedDateTime

введите описание изображения здесь

Думайте о ZonedDateTime концептуально как о Instant с назначенным ZoneId.


ZonedDateTime = ( Instant + ZoneId )


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

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 

Почти весь ваш серверный сервер, база данных, бизнес-логика, сохранение данных, обмен данными должны быть в UTC. Но для представления пользователям вам нужно настроить часовой пояс, ожидаемый пользователем. Это назначение ZonedDateTime класса и классов форматирования, используемых для генерации строковых представлений этих значений даты и времени.

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ; // Standard ISO 8601 format.

Вы можете сгенерировать текст в локализованном формате с помощью DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;

mardi 30 avril 2019 à 23 h 22 min 55 s heure de l’Inde


LocalDate, LocalTime, LocalDateTime

Диаграмма, показывающая только календарь для LocalDate.

Диаграмма, показывающая только часы для локального времени.

Диаграмма, показывающая календарь плюс часы для LocalDateTime.

"Локальные" классы даты и времени, LocalDateTime, LocalDate, LocalTime это другой вид программ. Они не привязаны к какой-либо одной местности или часовому поясу. Они не привязаны к временной шкале. Они не имеют реального значения до тех пор, пока вы не примените их к местности, чтобы найти точку на временной шкале.

Слово “Local” в этих именах классов может показаться нелогичным для непосвященных. Это слово означает любой населенный пункт или каждую местность, но не конкретную местность.

Итак, для бизнес-приложений "Локальные" типы используются не часто, поскольку они представляют лишь общее представление о возможной дате или времени, а не конкретный момент на временной шкале. Бизнес-приложения, как правило, заботятся о точном моменте поступления счета, отправки товара на транспортировку, найма сотрудника или выезда такси из гаража. Итак, разработчики бизнес-приложений чаще всего используют классы Instant и ZonedDateTime.

Итак, когда мы будем использовать LocalDateTime? В трех ситуациях:


  • Мы хотим применить определенную дату и время суток в нескольких местоположениях.

  • Мы бронируем встречи.

  • У нас предполагаемый, но не определенный часовой пояс.

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

Одно время суток, несколько моментов

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

Например, "Рождество начинается в полночь 25 декабря 2015 года" - это LocalDateTime. Полночь в Париже пробивает в разное время, чем в Монреале, и снова отличается в Сиэтле и в Окленде.

LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ; // 00:00:00
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ; // Christmas morning anywhere.

Другой пример: "Компания Acme придерживается политики, согласно которой обеденное время начинается в 12: 30 на каждом из ее заводов по всему миру" - это LocalTime. Чтобы получить реальное значение, вам нужно применить его к временной шкале, чтобы определить момент 12:30 на заводе в Штутгарте, или 12:30 на заводе в Рабате, или 12: 30 на заводе в Сиднее.

Бронирование встреч

Другая ситуация, которую можно использовать LocalDateTime, - это бронирование будущих мероприятий (например, визитов к стоматологу). Эти встречи могут быть назначены достаточно далеко в будущем, и вы рискуете, что политики переопределят часовой пояс. Политики часто мало предупреждают, а то и вовсе не предупреждают. Если вы имеете в виду "15:00 следующего дня, 23 января", независимо от того, как политики могут играть с часами, то вы не можете записать момент – это привело бы к тому, что 15:00 превратились бы в 14:00 или 16:00, если бы этот регион, например, принял или отменил летнее время.

Для назначений храните a LocalDateTime и a ZoneId отдельно. Позже, при генерации расписания, "на лету" определите момент, вызвав LocalDateTime::atZone( ZoneId ) для генерации ZonedDateTime объекта.

ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.

При необходимости вы можете настроить UTC. Извлеките Instant из ZonedDateTime.

Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.

Неизвестная зона

Некоторые люди могут использовать LocalDateTime в ситуации, когда часовой пояс или смещение неизвестны.

Я считаю этот случай неуместным. Если зона или смещение предназначены, но не определены, у вас неверные данные. Это было бы похоже на сохранение цены продукта без указания предполагаемой валюты (доллары, фунты, евро и т.д.). Не очень хорошая идея.

Все типы даты и времени

Для полноты картины приведем таблицу всех возможных типов даты и времени, как современных, так и устаревших в Java, а также тех, которые определены стандартом SQL. Это может помочь поместить классы Instant & LocalDateTime в более широкий контекст.

Таблица всех типов даты и времени в Java (как современной, так и устаревшей), а также стандартной SQL.

Обратите внимание на странный выбор, сделанный командой Java при разработке JDBC 4.2. Они решили поддерживать все времена java.time ... за исключением двух наиболее часто используемых классов: Instant & ZonedDateTime.

Но не стоит беспокоиться. Мы можем легко конвертировать туда и обратно.

Преобразование Instant.

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Преобразование ZonedDateTime.

// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;

О java.time

Платформа java.time встроена в Java 8 и более поздние версии. Эти классы заменяют старые, вызывающие беспокойство, устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, ознакомьтесь с Руководством по Oracle. И найдите в Stack Overflow множество примеров и пояснений. Спецификация - JSR 310.

Проект Joda-Time, который сейчас находится в режиме обслуживания, рекомендует перейти на классы java.time.

Вы можете обмениваться объектами java.time непосредственно со своей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах. Поддержка Hibernate 5 и JPA 2.2 java.time.

Где получить классы java.time?

Таблица того, какую библиотеку java.time использовать с какой версией Java или Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательным полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и больше.

Ответ 2

Одним из основных отличий является "локальная" часть LocalDateTime. Если вы живете в Германии и создаете LocalDateTime экземпляр, а кто-то другой живет в США и создает другой экземпляр в тот же самый момент (при условии, что часы установлены правильно) - значение этих объектов на самом деле будет другим. Это не относится к Instant, который вычисляется независимо от часового пояса.

LocalDateTime дата и время хранятся без часового пояса, но их начальное значение зависит от часового пояса. Instant's - нет.

Более того, LocalDateTime предоставляет методы для манипулирования компонентами даты, такими как дни, часы и месяцы. An Instant этого не делает.


помимо преимущества в наносекундной точности Instant и части часового пояса в LocalDateTime


Оба класса имеют одинаковую точность. LocalDateTime не сохраняет часовой пояс. Внимательно читайте Javadocs, потому что вы можете совершить большую ошибку с такими неверными предположениями: Instant и LocalDateTime.

Ответ 3

Вы ошибаетесь насчет LocalDateTime: он не хранит никакой информации о часовом поясе и имеет наносекундную точность. Цитирую Javadoc (выделено мной):


Дата-время без часового пояса в календарной системе ISO-8601, например 2007-12-03T10:15:30.


LocalDateTime это неизменяемый объект date-time, который представляет дату-время, часто рассматриваемый как год-месяц-день-час-минута-секунда. Также доступны другие поля даты и времени, такие как day-of-year, day-of-week и week-of-year. Время представлено с точностью до наносекунды. Например, значение "2 октября 2007 года в 13:45.30.123456789" может храниться в LocalDateTime.


Разница между ними заключается в том, что Instant представляет смещение от эпохи (01-01-1970) и, как таковой, представляет конкретный момент времени на временной шкале. Два Instant объекта, созданные в один и тот же момент в двух разных местах на Земле, будут иметь точно такое же значение.

Ответ 4

LocalDateTime не содержит информации о часовом поясе: одно LocalDateTime может представлять разные моменты времени для разных машин по всему миру. Поэтому вам не следует пытаться использовать его с неявным часовым поясом (системным по умолчанию). Вы должны использовать это для того, что оно представляет, например, "Новый год 1 января, в 0: 00": это означает разное время во всех точках земного шара, но в данном случае это необходимо.

Instant - это момент времени в часовом поясе по Гринвичу. Используйте его в дополнение к часовому поясу пользователя, например, чтобы показать ему начало встречи в его часовом поясе.

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

Вот простая синтетическая схема для получения общей картины классов в пакете java.time и их связи со стандартом ISO-8601, используемым для надежного и легкого обмена датами и временем между Java и другими языками или фреймворками:

Классы пакета java.time и их связь со стандартом ISO-8601

Схема подробно объясняется здесь: http://slaout.linux62.org/java-date-time /

java java-8