Подтвердить что ты не робот

Какая разница между Instant и LocalDateTime?

Я знаю, что:

  • Мгновенный - скорее "техническое" представление временной метки (наносекунды) для вычислений.
  • LocalDateTime - это скорее представление даты и времени, включая временные зоны для людей.

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

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

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

4b9b3361

Ответ 1

Table of types of date-time class in modern java.time versus legacy.

ТЛ; др

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

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

Неверная презумпция

LocalDateTime is rather date/clock representation including time-zones for humans.

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

Чтобы процитировать этот класс документа:

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

Таким образом, Local… означает "не зонировано, нет смещения".

Instant

enter image description here

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

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

OffsetDateTime

Класс OffsetDateTime представляет момент и дату и время с контекстом, состоящим из некоторого количества часов, минут и секунд, предшествующих UTC или позади него. Величина смещения, количество часов, минут и секунд, представлена классом ZoneOffset.

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

ZoneOffset

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

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

ZoneId

enter image description here

часовой пояс представлен классом 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

enter image description here

Думайте о 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 lInde

LocalDate, LocalTime, LocalDateTime

Diagram showing only a calendar for a <code>LocalDate</code>.

Diagram showing only a clock for a <code>LocalTime</code>.

Diagram showing a calendar plus clock for a <code>LocalDateTime</code>.

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

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

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

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

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

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

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

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

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

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

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

Для встреч храните LocalDateTime и 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 классы в более широком контексте.

Table of all date-time types in Java (both modern & legacy) as well as SQL standard.

Обратите внимание на странный выбор, сделанный командой 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.

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

Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите в Кару множество примеров и объяснений. Спецификация: JSR 310.

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

Где взять классы java.time?

  • Java SE 8, Java SE 9, Java SE 10 и более поздние версии
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые мелкие функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 & 7 в ThreeTen-Backport.
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранних версий Android (& lt; 26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянуто выше). Смотрите Как использовать ThreeTenABP....

Table of which java.time library to use with which version of Java or Android

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

Instant соответствует времени на первом меридиане (Гринвич).

В то время как LocalDateTime относительно настроек часового пояса ОС и

не может представлять момент без дополнительной информации, такой как смещение или временная зона.