Как получить дату UTC + 0 в Java 8?

108

У меня проблемы с классом Date в Java. Класс Date возвращает дату локального компьютера, но мне нужен UTC-0.

Я погуглил и нашел отличное решение для JavaScript, но для Java ничего полезного.

Как получить дату UTC + 0 в Java 8?

отметка
источник
12
java.util.Dateникогда не является датой локального компьютера. Он всегда определяется как прошедшие миллисекунды с 01.01.1970 относительно UTC + 00:00. Возможно, toString()вас смущает поведение его метода , который действительно использует представление в местном часовом поясе.
Мено Хохшильд,
Один вероятный ответ можно найти в вопросе: stackoverflow.com/questions/45350095/…
Priya Jain

Ответы:

146

С Java 8 вы можете написать:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

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

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toInstant().toEpochMilli();
ассилий
источник
1
Спасибо. можно ZonedDateTime преобразовать в Date или в long (ms)?
Марк
7
Хотя код этого ответа технически работает, не было бы более подходящим использовать OffsetDateTime, ZonedDateTimeесли бы мы работали с простым смещением от UTC, а не с полным часовым поясом?
Basil Bourque
1
Не было utc.toInstant().toEpochMilli()бы более точного преобразования в миллис?
iwat0qs
Безусловно, спасибо.
assylias
179

tl; dr

Instant.now()

java.time

Утомительные старые классы даты и времени, входящие в состав самых ранних версий Java, были вытеснены классами java.time, встроенными в Java 8 и более поздних версий . См. Учебное пособие по Oracle . Большая часть функциональности была перенесена на Java 6 и 7 в ThreeTen-Backport и дополнительно адаптирована для Android в ThreeTenABP .

Instant

Значок Instantпредставляет собой момент на временной шкале в формате UTC с разрешением до наносекунд .

Instant instant = Instant.now();

toStringМетод создает объект типа String с текстом , представляющим значение даты и время , используя один из стандартных ISO 8601 форматов.

String output = instant.toString();  

2016-06-27T19: 15: 25.864Z

InstantКласс является основным классом многокомпонентного в java.time. Это должен быть ваш класс при обработке даты и времени, так как обычно лучше всего отслеживать, хранить и обмениваться значениями даты и времени в формате UTC.

OffsetDateTime

Но Instantимеет ограничения, такие как отсутствие параметров форматирования для создания строк в альтернативных форматах. Для большей гибкости конвертируйте из Instantв OffsetDateTime. Укажите смещение от UTC . В java.time это означает ZoneOffsetобъект. Здесь мы хотим придерживаться UTC (+00), чтобы мы могли использовать удобную константу ZoneOffset.UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

2016-06-27T19: 15: 25.864Z

Или пропустите Instantзанятия.

OffsetDateTime.now( ZoneOffset.UTC )

Теперь, имея OffsetDateTimeобъект в руках, вы можете использовать его DateTimeFormatterдля создания объектов String с текстом в альтернативных форматах. Найдите множество примеров использования DateTimeFormatter.

ZonedDateTime

Если вы хотите отобразить время на настенных часах для определенного часового пояса, примените a, ZoneIdчтобы получить ZonedDateTime.

В этом примере мы применяем часовой пояс Монреаля. Летом при ерунде перехода на летнее время (DST) зона имеет смещение -04:00. Итак, обратите внимание, что время суток в выводе на четыре часа раньше, 15а не 19часов. Instantи ZonedDateTimeоба представляют собой один и тот же одновременный момент, только рассматриваемый через две разные линзы.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

2016-06-27T15: 15: 25.864-04: 00 [Америка / Монреаль]

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

Хотя вам следует избегать старых классов даты и времени, при необходимости вы можете преобразовать, используя новые методы, добавленные к старым классам. Здесь мы используем java.util.Date.from( Instant )и java.util.Date::toInstant.

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

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

Instant instant= utilDate.toInstant();

Точно так же ищите новые методы, добавленные к GregorianCalendar(подклассу Calendar) для преобразования в и из java.time.ZonedDateTime.

Таблица типов классов даты и времени в современном java.time по сравнению с устаревшим.

О java.time

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

Чтобы узнать больше, см. Oracle Tutorial . И поищите в 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?

Василий Бурк
источник
3
Благодарю за то, что говорят, что летнее время - это
ерунда
так что, если бы DST не существовало ZonedDateTime, не было бы необходимости, так как все ZoneIdбыло бы сопоставлено с тем, что ZoneOffsetмы могли бы просто использовать OffsetDateTime?
Wilmol
1
@wilmol Нет. Переход на летнее время (DST) - лишь одна из многих причин, по которым политики решают переопределить границы часовых поясов и смещения внутри этих зон. Недавно Северная Корея изменила свои часы на полчаса, чтобы синхронизировать их с Южной Кореей по дипломатическим причинам. Во время войны захватчики / оккупанты могут изменить смещение, чтобы оно соответствовало смещению в родной стране. В настоящее время появилась новая мода, когда правительства предпочитают прекратить переход на летнее время, но постоянно остаются на летнем времени, а не возвращаются к своему предыдущему стандартному времени. Всегда планируйте смещение каждой смены зоны, иначе ваше приложение в конечном итоге сломается.
Basil
1
Фантастический ответ! Я очень ценю время, которое вы вложили в это. :)
drognisep 04
ZoneId.of («Америка / Монреаль»); зачем кому-то изобретать такое в jdk? он уродлив, отвратителен, не говорит, что что-то не так, до времени выполнения, кто может запомнить весь этот жесткий код? почему бы не использовать это в классе ENUM?
workplaylifecycle
4

В java8 я бы использовал Instantкласс, который уже находится в UTC и с которым удобно работать.

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

В качестве альтернативы вы можете использовать следующее:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

Вернуться к Instant

Instant ins4 = Instant.from(odt);
Абель Терефе
источник
3
Нет, в этом Instantесть не по местному времени. По Instantопределению находится в формате UTC. Так что нет необходимости в махинациях, замеченных в этом Ответе, при попытке попасть в UTC; Instantуже находится в UTC. См. Мой ответ для получения дополнительной информации и более простого кода.
Basil Bourque
Спасибо за комментарий.
Abel
0

Однострочное решение в Java 8:

public Date getCurrentUtcTime() {
    return Date.from(Instant.now());
}
Абхиджит Ашок Мунешвар
источник
java.util.Dateустарела.
Николай