В чем разница между Instant и LocalDateTime?
Я знаю это:
- Instant - это скорее "техническое" представление временных меток (наносекунд) для вычислений.
- LocalDateTime - это скорее представление даты / часов, включая часовые пояса для людей.
Тем не менее, в конце концов, IMO можно использовать как тип для большинства вариантов применения. Как пример: в настоящее время я выполняю пакетное задание, в котором мне нужно рассчитать следующий прогон на основе дат, и я изо всех сил пытаюсь найти плюсы / минусы между этими двумя типами (кроме преимущества точности в наносекундах в Instant и части часового пояса). LocalDateTime).
Можете ли вы назвать примеры приложений, в которых следует использовать только Instant или LocalDateTime?
Изменить: Остерегайтесь неправильно прочитанных документов для LocalDateTime относительно точности и часового пояса
7 ответов
Неверная презумпция
LocalDateTime - это скорее представление даты / часов, включая часовые пояса для людей.
Ваше утверждение неверно: A LocalDateTime
не имеет часового пояса. Отсутствие часового пояса - весь смысл этого класса.
Чтобы процитировать этот класс 'документ:
Этот класс не хранит и не представляет часовой пояс. Вместо этого это описание даты, используемой для дней рождений, в сочетании с местным временем, показанным на настенных часах. Он не может представлять момент на временной шкале без дополнительной информации, такой как смещение или часовой пояс.
Так Local…
означает "не зонирован".
Мгновенный
Instant
это момент на временной шкале в UTC, подсчет наносекунд со времени первого момента 1970 UTC (в основном, см. подробности в документе doc). Поскольку большая часть вашей бизнес-логики, хранилища данных и обмена данными должна быть в формате UTC, это удобный класс, который часто используется.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
ZoneId
ZoneId
это часовой пояс.
Часовой пояс смещен на столько часов и минут от UTC. Например, в Париже новый день наступает раньше, чем в Монреале. Поэтому нам нужно передвинуть стрелки часов, чтобы лучше отразить полдень (когда Солнце находится прямо над головой) для данного региона. Чем дальше на восток / запад от линии UTC в Западной Европе / Африке, тем больше смещение.
Кроме того, часовой пояс - это набор правил для обработки корректировок и аномалий, практикуемых местным сообществом или регионом. Самая распространенная аномалия - слишком популярное безумие, известное как летнее время.
Часовой пояс имеет историю прошлых правил, настоящих правил и правил, подтвержденных на ближайшее будущее.
Эти правила меняются чаще, чем вы могли ожидать. Обязательно обновляйте правила библиотеки даты и времени, обычно копии базы данных 'tz'. Поддерживать актуальность теперь проще, чем когда-либо, в Java 8, когда Oracle выпустила средство обновления часовых поясов.
Используйте правильные имена часовых поясов. Эти имена принимают форму континента плюс слеш плюс город или регион. Избегайте 3-4-буквенных кодов, таких как EST
или же IST
, Они не стандартизированы и не уникальны. Они также путают беспорядок ДСТ.
Часовой пояс = смещение + правила настроек
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
Иногда у нас есть только смещение без правил. Java предоставляет ZoneOffset
для этой цели подкласс ZoneId
, Обратите внимание на удобную константу, определенную там, ZoneOffset.UTC
,
ZoneOffset offset = ZoneOffset.of( -5 , 0 ) ; // “-05:00”
ZonedDateTime
Думать о ZonedDateTime
концептуально как Instant
с назначенным ZoneId
,
ZonedDateTime = ( Instant + ZoneId)
Почти все ваши бэкэнд, база данных, бизнес-логика, постоянство данных, обмен данными должны быть в UTC. Но для представления пользователям необходимо настроить часовой пояс, ожидаемый пользователем. Это цель ZonedDateTime
класс и классы форматера, используемые для генерации строковых представлений этих значений даты и времени.
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDateTime, LocalDate, LocalTime
"Местные" классы даты и времени, LocalDateTime
, LocalDate
, LocalTime
, другой вид твари. Они не привязаны ни к одной местности или часовому поясу. Они не привязаны к временной шкале. Они не имеют никакого реального смысла, пока вы не примените их к местности, чтобы найти точку на временной шкале.
Например, "Рождество начинается в полночь 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 на фабрике в Сиднее.
Поэтому для бизнес-приложений "локальные" типы используются не часто, поскольку они представляют только общее представление о возможной дате или времени, а не о конкретном моменте на временной шкале. Бизнес-приложения, как правило, заботятся о точном моменте поступления счета-фактуры, о продукте, отправленном для перевозки, о найме сотрудника или о выходе такси из гаража. Так что разработчики бизнес-приложений используют Instant
а также ZonedDateTime
почти исключительно. С другой стороны, вы должны рассмотреть возможность использования Local…
типы для бронирования будущих событий (например, встречи с дантистами) достаточно далеко в будущем, когда вы рискуете, чтобы политики уточнили часовой пояс с небольшим предупреждением, как это часто бывает.
О java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые классы даты и времени, такие как java.util.Date
, Calendar
& SimpleDateFormat
,
Проект Joda-Time, находящийся сейчас в режиме обслуживания, рекомендует перейти на классы java.time.
Чтобы узнать больше, смотрите Oracle Tutorial. И поиск переполнения стека для многих примеров и объяснений. Спецификация 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 (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
и многое другое.
Одним из основных отличий является Local
часть LocalDateTime
, Если вы живете в Германии и создаете LocalDateTime
экземпляр и кто-то еще живет в США и создает другой экземпляр в тот же момент (при условии, что часы установлены правильно) - значение этих объектов на самом деле будет другим. Это не относится к Instant
, который рассчитывается независимо от часового пояса.
LocalDateTime
сохраняет дату и время без часового пояса, но его начальное значение зависит от часового пояса. Instant
это не так.
Более того, LocalDateTime
предоставляет методы для манипулирования такими компонентами даты, как дни, часы, месяцы. Instant
не.
Помимо преимущества наносекундной точности Instant и часового пояса LocalDateTime
Оба класса имеют одинаковую точность. LocalDateTime
не хранит часовой пояс. Внимательно прочитайте javadocs, потому что вы можете сделать большую ошибку с такими неверными предположениями: Instant и LocalDateTime.
Вы ошибаетесь по поводу LocalDateTime
: он не хранит никакой информации о часовом поясе и обладает точностью до наносекунды. Цитирую Javadoc (выделение мое):
Дата-время без часового пояса в календарной системе ISO-8601, например, 2007-12-03T10: 15: 30.
LocalDateTime - это неизменный объект даты-времени, который представляет дату-время, часто рассматриваемый как год-месяц-день-час-минута-секунда. Другие поля даты и времени, такие как день года, день недели и неделя года, также могут быть доступны. Время представляется с точностью до наносекунды. Например, значение "2 октября 2007 года в 13:45.30.123456789" может быть сохранено в LocalDateTime.
Разница между ними заключается в том, что Instant
представляет смещение от эпохи (01-01-1970) и, как таковое, представляет определенный момент на временной шкале. Два Instant
объекты, созданные в один и тот же момент в двух разных местах Земли, будут иметь абсолютно одинаковое значение.
LocalDateTime не имеет информации о часовом поясе: один LocalDateTime может представлять разные моменты времени для разных машин по всему миру. Поэтому вам не следует пытаться использовать его с неявным часовым поясом (по умолчанию в системе). Вы должны использовать его для того, что он представляет, например, «Новый год — 1 января в 0:00»: это означает разное время во всех точках земного шара, но в данном случае это необходимо.
Instant — это момент времени в часовом поясе Гринвича. Используйте его в дополнение к часовому поясу пользователя, чтобы, например, показать ему/ей начало встречи в его/ее часовом поясе.
Если эти два класса не представляют то, что вы хотели сохранить/обменять, то, возможно, ZonedDateTime или другой класс справятся лучше.
Вот простая синтетическая схема, чтобы получить общее представление о классах в пакете java.time и их отношении к стандарту ISO-8601, используемому для надежного и простого обмена датами и временем между Java и другими языками или фреймворками:
Схема подробно описана здесь: http://slaout.linux62.org/java-date-time/
За свою карьеру я имел дело с часовыми поясами во многих проектах. Оглядываясь назад, я должен признать, что мы никогда не понимали это на 100% правильно из-за удивительной сложности темы. Вот почему я решил написать с подробным описанием пакета.
Уже есть много отличных ответов на вопрос, заданный выше, но эта выходит за рамки только Java и также охватывает взаимодействие с такими технологиями, как реляционные базы данных, базы данных NoSQL (например, MongoDB) или JavaScript, которые обычно имеют гораздо более ограниченную поддержку, чем Java. когда дело касается часовых поясов.
Хотя я рекомендую прочитать , чтобы получить подробное представление обо всех концепциях, я хотел бы добавить две схемы из моего поста, чтобы дать краткий обзор.
На первой диаграмме представлены особенностиjava.time
классы, которые описывают момент времени. Некоторые классы обозначают абсолютный (или однозначный) момент времени (называемый моментом), в то время как другим нравитсяLocalDateTime
опишите только так называемое время настенных часов:
Вторая схема представляет собой дерево решений, которое поможет вам выбрать правильный класс для вашего варианта использования.
Некоторые решения, которые необходимо принять в этом дереве решений, далеко не тривиальны. Более подробно это описано в пост в блогемоем блогестатьюзапись в блоге .
Instant
соответствует времени на простом меридиане (Гринвич).
В то время как LocalDateTime
относительно настроек часового пояса ОС, и
не может представлять момент без дополнительной информации, такой как смещение или часовой пояс.
Почему ответы такие сложные? Грубо говоря, у них обоих нет часового пояса. Но Instant считается UTC, когда Local означает ваше усмотрение.