Преобразовать java.util.Date для какого типа "java.time"?

У меня есть java.util.Date объект или java.util.Calendar объект. Как мне преобразовать это в правильный тип в фреймворке java.time?

Я слышал, что теперь мы должны выполнять основную часть нашей бизнес-логики с типами java.time. При работе со старым кодом, который еще не обновлен для java.time, я должен иметь возможность конвертировать туда и обратно. Какие типы карт для java.util.Date или же java.util.Calendar?

1 ответ

Решение

Да, вам определенно следует использовать фреймворк java.time, когда это возможно.

Избегайте старых классов даты и времени

Старые классы даты и времени, включая java.util.Date, java.util.Calendar, а также java.text.SimpleTextFormat и такие оказались плохо продуманными, запутанными и хлопотными. Избегайте их, где вы можете. Но когда вы должны взаимодействовать с этими старыми типами, вы можете конвертировать между старым и новым.

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

java.time

Инфраструктура java.time определяется JSR 310, вдохновлена ​​чрезвычайно успешной библиотекой Joda-Time и расширена проектом ThreeTen-Extra. Большая часть функциональности была перенесена на Java 6 & 7 в проекте ThreeTen-Backport с дальнейшей адаптацией для Android в проекте ThreeTenABP.

Какой тип java.time соответствует java.util.Date? Ну а java.util.Date Объект в основном представляет момент на временной шкале в UTC, комбинацию даты и времени суток. Мы можем перевести это на любой из нескольких типов в java.time. Каждый обсуждается ниже. Обратите внимание, что некоторые старые методы были добавлены к старым классам даты и времени, чтобы облегчить преобразования.

диаграмма преобразования из java.util.Date/.Calendar через ZonedDateTime (или OffsetDateTime) в три типа <code>Instant</code></h2><p>Строительный блок в java.time является <code>Instant</code>, момент на временной шкале в <a href=UTC с разрешением наносекунд.

Как правило, вы должны делать большую часть своей бизнес-логики в UTC. В такой работе, Instant будет использоваться часто. Пройти вокруг Instant объекты, применяя часовой пояс только для представления пользователю. Если вам нужно применить смещение или часовой пояс, используйте типы, описанные ниже.

От java.util.Date в Instant

Учитывая, что оба Instant а также java.util.Date момент на временной шкале в UTC, мы можем легко перейти от java.util.Date для Instant, Старый класс получил новый метод, java.util.Date::toInstant,

Instant instant = myUtilDate.toInstant();

Вы можете пойти в другом направлении, от Instant к java.util.Date, Но вы можете потерять информацию о доли секунды. Instant отслеживает наносекунды, до девяти цифр после десятичной точки, такие как 2016-01-23T12:34:56.123456789Z, И java.util.Date &.Calendar ограничены миллисекундами, до трех цифр после десятичного знака, таких как 2016-01-23T12:34:56.123Z, В этом примере происходит от Instant в Date означает усечение 456789,

java.util.Date myUtilDate = java.util.Date.from( instant );

От java.util.Calendar в Instant

Как насчет java.util.Calendar вместо java.util.Date? Внутренний для Calendar объект даты время отслеживается как подсчет миллисекунд от опорной эпохи даты и времени первого момента в 1970 UTC (1970-01-01T00:00:00.0Z). Таким образом, это значение может быть легко преобразовано в Instant,

Instant instant = myUtilCalendar.toInstant() ;

От java.util.GregorianCalendar в ZonedDateTime

Еще лучше, если ваш java.util.Calendar объект на самом деле java.util.GregorianCalendar Вы можете легко перейти прямо к ZonedDateTime, Этот подход имеет преимущество сохранения встроенной информации о часовом поясе.

Даункаут с интерфейса Calendar к конкретному классу GregorianCalendar, Затем позвоните toZonedDateTime а также from методы, чтобы идти вперед и назад.

if( myUtilCalendar instanceof GregorianCalendar ) {
    GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
    ZonedDateTime zdt = gregCal.toZonedDateTime();  // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
end if 

Идти в другом направлении...

    java.util.Calendar myUtilCalendar = java.util.GregorianCalendar.from( zdt ); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.

Как обсуждалось выше, будьте осторожны, что вы можете потерять информацию о доле секунды. Наносекунды в типе java.time (ZonedDateTime) усекается до миллисекунд в .Calendar / .GregorianCalendar,

OffsetDateTime

Из Instant мы можем применить смещение от UTC, чтобы перейти во время настенных часов для некоторой местности. Смещение - это количество часов и, возможно, минут и секунд, перед UTC (на восток) или позади UTC (на запад). ZoneOffset класс представляет эту идею. Результатом является OffsetDateTime объект.

ZoneOffset offset = ZoneOffset.of( "-04:00" ); 
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );

Вы можете пойти в другом направлении, от OffsetDateTime к java.util.Date, Извлечь Instant а затем продолжайте, как мы видели в коде выше. Как обсуждалось выше, любые наносекунды усекаются до миллисекунд (потеря данных).

java.util.Date myUtilDate = java.util.Date.from( odt.toInstant() );

ZonedDateTime

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

Применяя ZoneId дает вам ZonedDateTime объект. Используйте правильное название часового пояса (континент / регион). Никогда не используйте 3-4 буквенные сокращения, такие как EST или же IST поскольку они не стандартизированы и не уникальны.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Вы можете пойти в другом направлении, от ZonedDateTime к java.util.Date, Извлечь Instant а затем продолжайте, как мы видели в коде выше. Как обсуждалось выше, любые наносекунды усекаются до миллисекунд (потеря данных).

java.util.Date myUtilDate = java.util.Date.from( zdt.toInstant() );

И мы увидели выше, что ZonedDateTime может быть преобразован в GregorianCalendar,

LocalDate

Иногда вам может понадобиться значение только для даты, без времени суток и без часового пояса. Для этого используйте java.time.LocalDate объект.

См. Этот вопрос для дальнейшего обсуждения. Преобразуйте java.util.Date в java.time.LocalDate, особенно этот ответ, написанный главным человеком, придумавшим изобретение Joda-Time и java.time.

Ключ должен пройти через ZonedDateTime (как сгенерировано в коде выше). Нам нужен часовой пояс, чтобы определить дату. Дата меняется по всему миру, с новым днем ​​на востоке. Например, после полуночи в Париже новый день, а в Монреале все еще "вчера". Так что пока LocalDate не содержит часовой пояс, часовой пояс необходим для определения LocalDate,

LocalDate localDate = zdt.toLocalDate();

Конвертировать в другом направлении от LocalDate дата-время означает придумывать время суток. Вы можете выбрать любое время суток, которое имеет смысл в вашем бизнес-сценарии. Для большинства людей первый момент дня имеет смысл. Вы можете испытать желание написать жесткий код в этот первый момент, как время 00:00:00.0, В некоторых часовых поясах это время может быть недействительным в качестве первого момента из-за перехода на летнее время (DST) или других аномалий. Так пусть java.time определит правильное время с помощью вызова atStartOfDay,

ZonedDateTime zdt = localDate.atStartOfDay( zoneId );

LocalTime

В редких случаях вам может потребоваться только время суток без даты и без часового пояса. Эта концепция представлена LocalTime учебный класс. Как обсуждено выше с LocalDate нам нужен часовой пояс, чтобы определить LocalTime хотя LocalTime объект не содержит (не "запоминает") этот часовой пояс. Итак, снова мы проходим ZonedDateTime объект, полученный из Instant как видно выше.

LocalTime localTime = zdt.toLocalTime();

LocalDateTime

Как и с двумя другими Local… типы, а LocalDateTime не имеет ни часового пояса, ни смещения. Таким образом, вы можете использовать это редко. Это дает вам приблизительное представление о дате и времени, но не является точкой на временной шкале. Используйте это, если вы имеете в виду некоторую общую дату и время, которое может быть применено к часовому поясу.

Например, "Рождество начинается в этом году" будет 2016-12-25T00:00:00.0, Обратите внимание на отсутствие какого-либо смещения или часового пояса в этом текстовом представлении LocalDateTime, Рождество в Дели начинается раньше, чем в Париже во Франции, а позже - в Монреале, Квебеке, Канада. Применение часового пояса каждой из этих областей даст другой момент на временной шкале.

LocalDateTime ldt = zdt.toLocalDateTime();
Другие вопросы по тегам