Как получить временную метку UTC из Календаря?
В Java, когда я использую Calendar.getInstance();
, я получаю объект Calendar
для текущего часового пояса. Но java.sql.Timestamp
обычно хранится в UTC Time, а не по местному времени. Итак, как я могу получить время UTC из экземпляра календаря?
DateFormat df = DateFormat.getTimeInstance();
Calendar cal = Calendar.getInstance();
Timestamp time = new Timestamp(cal.getTimeInMillis());
// Prints local time
System.out.println(df.format(new Date(time.getTime())));
// Printe local time, but I want UTT Time
System.out.println("timestamp: " + time);
Ответы
Ответ 1
Когда вы вызываете Calendar.getTime()
, это даст вам значение, которое не имеет соответствующего часового пояса, или вы можете думать о нем как находящемся в UTC - в тот момент, когда отображается календарь. Так что, если бы это было (скажем) 9 утра в часовом поясе календаря, это может быть 5 вечера UTC.
Теперь java.util.Date
(и я бы предположил, что Timestamp
) будет отформатирован в системном часовом поясе по умолчанию, когда вы вызываете toString()
(неявно или явно), но не позволяйте этому обмануть вас в мысли, что часовой пояс является частью данных внутри самого объекта.
Вам нужно четко указать, что именно вы пытаетесь достичь - и тогда вы, вероятно, обнаружите, что Joda Time позволяет вам выражайте, что код лучше, чем встроенные библиотеки.
Ответ 2
Ваш код уже делает именно то, что вы хотите. Timestamp
(а также Date
) не имеет информации о часовом поясе и всегда должен содержать отметку времени по Гринвичу (которая возвращает то, что возвращает Calendar.getTimeInMillis()
).
Резонанс, по которому вы видите локальное время печати, заключается в том, что методы DateFormat
factory, а также Timestamp.toString()
неявно используют системный часовой пояс.
Ответ 3
TL;DR
Instant.now()
Избегать устаревших классов времени
Вы используете неприятные старые классы времени, которые теперь вытесняются классами java.time. Не нужно использовать DateFormat
, Calendar
или Timestamp
.
Если вы должны взаимодействовать с Calendar
из старого кода, еще не обновленного до java.time, конвертировать с использованием новых методов, добавленных в старых классов. Извлеките устаревшее java.util.Date
и преобразуйте в Instant
.
Instant instant = myCal.getTime().toInstant() ;
Использование java.time
Получить текущий момент как Instant
. Класс Instant
представляет момент на временной шкале в UTC с разрешением наносекунды (до девяти (9) цифр десятичной дроби).
Instant instant = Instant.now() ;
2017-02-17T03: 29: 15.725Z
База данных
С помощью JDBC 4.2 и более поздних версий вы можете напрямую обменивать объект Instant
с вашей базой данных. Поэтому нет необходимости в устаревших java.sql.Timestamp
.
myPreparedStatement.setObject( … , instant ) ;
И поиск:
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Подсчет с эпохи
По-видимому, вам нужно несколько миллисекунд с эталонной даты эпохи 1970-01-01T00:00:00Z
. Вы можете извлечь это число из Instant
. Но будьте осторожны с потерей данных, так как Instant
имеет разрешение наносекунд, которое вы будете усекать до миллисекунды.
long millis = instant.toEpochMilli() ;
1487302155725
О java.time
Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date
, Calendar
и SimpleDateFormat
.
Проект Joda-Time, теперь режим обслуживания, советуем перейти к классам java.time.
Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация JSR 310.
Где получить классы java.time?
- Java SE 8 и SE 9 и позже
- Встроенный.
- Часть стандартного Java API с объединенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и SE 7
- Большая часть функциональных возможностей java.time портирована на Java 6 и 7 в ThreeTen-Backport.
- Android
Проект ThreeTen-Extra расширяет java.time с помощью дополнительных классов. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval
, YearWeek
, YearQuarter
и больше.
Ответ 4
Следующий фрагмент должен удовлетворять вашим требованиям:
df.setTimeZone(TimeZone.getTimeZone("UTC"));