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

Получить объект даты в формате UTC в Java

Я написал следующий код. Я хочу получить объект Date в формате UTC.

Я могу получить ожидаемую строку даты в UTC с помощью SimpleDateFormat. Но, используя тот же объект SimpleDateFormat, я не могу получить объект в формате UTC. Он возвращает объект в формате IST.

После поиска я обнаружил, что объект Date не сохраняет информацию о метке времени.

Как я могу получить объект даты в формате UTC?

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class dddd {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Input - "+1393572325000L);
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date= new Date(1393572325000L);  
        String dateString = formatter.format(date);

        System.out.println("Converted UTC TIME (using Format method) : "+dateString);

        Date date2 =null;
        try {
            date2 = formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }


        System.out.println("Parsed Date Object (using Parse method) : "+date2);

        System.out.println("Expected Date Object : Fri Feb 28 07:25:25 UTC 2014");

    }

}

Это выводит следующий результат:

Input - 1393572325000
Converted UTC TIME (using Format method) : 2014-02-28 07:25:25
Parsed Date Object (using Parse method) : Fri Feb 28 12:55:25 IST 2014
Expected Date Object : Fri Feb 28 07:25:25 UTC 2014
4b9b3361

Ответ 1

final Date currentTime = new Date();
final SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC time: " + sdf.format(currentTime));

Ответ 2

A Дата не имеет часового пояса. То, что вы видите, это только форматирование даты с помощью метода Date.toString(), который всегда использует ваш часовой пояс, чтобы преобразовать дату агностического времени в строку, которую вы можете понять.

Если вы хотите отображать дату агностического времени в виде строки, используя часовой пояс UTC, используйте SimpleDateFormat с часовым поясом UTC (как вы уже делаете в своем вопросе).

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

Ответ 3

TL;DR

Instant.ofEpochMilli ( 1_393_572_325_000L )
       .toString()

2014-02-28T07: 25: 25Z

Подробнее

(a) Вы, кажется, путаетесь, что такое дата. Как сказал ответ JB Nizet, дата отслеживает количество миллисекунд с Unix epoch (первый момент 1970 года) в UTC (то есть без смещения часового пояса). Таким образом, дата не имеет часовой пояс . И у него нет "формата". Мы создаем строковые представления из значения Date, но Дата сама по себе не является строкой и не имеет строки.

(b) Вы ссылаетесь на "формат UTC". UTC - это не формат, я не слышал. UTC (скоординированное универсальное время) является точкой отсчета часовых поясов. Часовые пояса к востоку от Королевской обсерватории в Гринвиче, Лондон, находятся на несколько часов и минут раньше UTC. Часовой пояс на запад отстает от UTC.

Кажется, вы ссылаетесь на строки ISO 8601. Вы используете дополнительный формат, опуская (1) T с середины и (2) смещение-от-UTC в конце. Если вы не представляете строку пользователю в пользовательском интерфейсе своего приложения, я предлагаю вам придерживаться обычного формата:

  • 2014-02-27T23:03:14+05:30
  • 2014-02-27T23:03:14Z ('Z' для Zulu или UTC со смещением +00: 00)

(c) Избегайте кодов часовых поясов 3 или 4 буквы. Они не являются ни стандартизированными, ни уникальными. Например, "IST" может означать либо индийское стандартное время, либо ирландское стандартное время.

(d) Попытайтесь приложить усилия к поиску StackOverflow перед публикацией. Вы бы нашли все свои ответы.

(e) Избегайте классов java.util.Date и Calendar в комплекте с Java. Они, как известно, хлопотно. Используйте либо Joda-Time, либо новый Java java.time Java 8s (вдохновленный Joda-Time, определенный JSR 310).

java.time

В классах java.time по умолчанию используются стандартные форматы ISO 8601 при разборе и генерации строк.

OffsetDateTime odt = OffsetDateTime.parse( "2014-02-27T23:03:14+05:30" ); 
Instant instant = Instant.parse( "2014-02-27T23:03:14Z" );

Проанализируйте количество миллисекунд с момента первого момента 1970 года в UTC.

Instant instant = Instant.ofEpochMilli ( 1_393_572_325_000L );

instant.toString(): 2014-02-28T07: 25: 25Z

Откорректируйте Instant в требуемый часовой пояс.

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

zdt.toString(): 2014-02-28T02: 25: 25-05: 00 [Америка/Монреаль]


О 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 и больше.


Joda времени

ОБНОВЛЕНИЕ: Проект Joda-Time, теперь в режим обслуживания, советуем перейти к классам java.time.

Joda-Time использует ISO 8601 в качестве значений по умолчанию.

Объект Joda-Time DateTime знает его в назначенный часовой пояс, в отличие от объекта java.util.Date.

Как правило, лучше указывать часовой пояс явно, а не полагаться на часовую зону по умолчанию.

Пример кода

long input = 1393572325000L;
DateTime dateTimeUtc = new DateTime( input, DateTimeZone.UTC );

DateTimeZone timeZoneIndia = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneIreland = DateTimeZone.forID( "Europe/Dublin" );

DateTime dateTimeIndia = dateTimeUtc.withZone( timeZoneIndia );
DateTime dateTimeIreland = dateTimeIndia.withZone( timeZoneIreland );

// Use a formatter to create a String representation. The formatter can adjust time zone if you so desire.
DateTimeFormatter formatter = DateTimeFormat.forStyle( "FM" ).withLocale( Locale.CANADA_FRENCH ).withZone( DateTimeZone.forID( "America/Montreal" ) );
String output = formatter.print( dateTimeIreland );

Дамп для консоли...

// All three of these date-time objects represent the *same* moment in the timeline of the Universe.
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "dateTimeIreland: " + dateTimeIreland );

System.out.println( "output for Montréal: " + output );

При запуске...

dateTimeUtc: 2014-02-28T07:25:25.000Z
dateTimeIndia: 2014-02-28T12:55:25.000+05:30
dateTimeIreland: 2014-02-28T07:25:25.000Z
output for Montréal: vendredi 28 février 2014 02:25:25

Собственно, java.util.Date имеет часовой пояс. Эта часовая зона назначается глубоко в исходном коде. Тем не менее класс игнорирует этот часовой пояс для большинства практических целей. И его метод toString применяет текущий часовой пояс JVM, а не внутренний часовой пояс. Смешение? Да. Это одна из многих причин избежать старых классов java.util.Date/.Calendar. Вместо этого используйте java.time и/или Joda-Time.

Ответ 4

В java 8 очень легко получить временную метку в UTC с помощью библиотеки java 8 java.time.Instant:

Instant.now();

Это небольшое слово кода вернет отметку времени UTC.

Ответ 5

Теперь вы можете вычесть разницу часовых поясов.

final Calendar calendar  = Calendar.getInstance();
final int      utcOffset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
final long     tempDate  = new Date().getTime();

return new Date(tempDate - utcOffset);