Как я могу получить текущую дату и время в UTC или GMT в Java? - PullRequest
431 голосов
/ 21 ноября 2008

Когда я создаю новый объект Date, он инициализируется текущим временем, но в местном часовом поясе. Как узнать текущую дату и время в GMT?

Ответы [ 31 ]

376 голосов
/ 21 ноября 2008

java.util.Date не имеет определенного часового пояса, хотя его значение чаще всего рассматривается по отношению к UTC. С чего ты взял, что по местному времени?

Если быть точным: значение в java.util.Date - это количество миллисекунд, прошедших с эпохи Unix, которая произошла в полночь 1 января 1970 года по Гринвичу. Та же самая эпоха также может быть описана в других часовых поясах, но традиционное описание относится к UTC. Так как это число в миллисекундах с фиксированной эпохи, значение в java.util.Date одинаково во всем мире в любой конкретный момент независимо от местного часового пояса.

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

Если проблема не в этом, отправьте пример кода.

Однако я бы порекомендовал вам в любом случае использовать Joda-Time , который предлагает гораздо более понятный API.

267 голосов
/ 27 марта 2010
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));

//Local time zone   
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");

//Time in GMT
return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
236 голосов
/ 28 октября 2013

ТЛ; др

Instant.now()   // Capture the current moment in UTC. 

Генерация строки для представления этого значения:

Instant.now().toString()  

2016-09-13T23: 30: 52.123Z

Подробнее

Как сказал правильный ответ Джона Скита , объект java.util.Date не имеет никакого часового пояса . Но его реализация toString применяет часовой пояс JVM по умолчанию при генерации строкового представления этого значения даты и времени. Смущает наивного программиста дата , кажется, имеет часовой пояс, но не имеет.

Классы java.util.Date, j.u.Calendar и java.text.SimpleDateFormat в комплекте с Java, как известно, доставляют много хлопот. Избегайте их. Вместо этого используйте любую из следующих компетентных библиотек даты и времени:

java.time (Java 8)

Java 8 предоставляет новый замечательный пакет java.time. * для замены старых классов java.util.Date/Calendar.

Получение текущего времени в UTC / GMT - простая однострочная…

Instant instant = Instant.now();

То, что класс Instant является основным строительным блоком в java.time, представляет момент на временной шкале в UTC с разрешением наносекунд .

В Java 8 текущий момент фиксируется только с разрешением до миллисекунд. В Java 9 реализована свежая реализация из Clock фиксирует текущий момент вплоть до полной наносекундной способности этого класса, в зависимости от возможностей тактового оборудования вашего хост-компьютера.

Этот метод toString генерирует строковое представление своего значения, используя один определенный формат ISO 8601 . Этот формат выводит ноль, три, шесть или девять цифр ( миллисекунд , микросекунд или наносекунд ) по мере необходимости для представления доли секунды.

Если вы хотите более гибкое форматирование или другие дополнительные функции, тогда примените нулевое смещение от UTC для самого UTC (ZoneOffset.UTC константа ), чтобы получить OffsetDateTime .

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

Дамп на консоль ...

System.out.println( "now: " + now );

При запуске…

now: 2014-01-21T23:42:03.522Z

Table of types of date-time classes in modern java.time versus legacy.

The java.time classes are defined by JSR 310 . Они были вдохновлены Joda-Time, но полностью перестроены.

Joda-Time

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

Используя Joda-Time стороннюю бесплатную библиотеку с открытым исходным кодом, вы можете получить текущую дату и время всего одной строкой кода.

Joda-Time вдохновил новые классы java.time. * В Java 8, но имеет другую архитектуру. Вы можете использовать Joda-Time в более старых версиях Java. Joda-Time продолжает работать на Java 8 и продолжает активно поддерживаться (по состоянию на 2014 год). Однако команда Joda-Time советует перейти на java.time.

System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );

Более подробный пример кода (Joda-Time 2.3)…

org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );

Дамп на консоль…

System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );

При запуске…

Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z

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

Часовой пояс

Я рекомендую вам всегда указывать часовой пояс, а не полагаться неявно на текущий часовой пояс JVM по умолчанию (который может измениться в любой момент!). Такое доверие, по-видимому, является распространенной причиной путаницы и ошибок в работе с датой и временем.

При звонке now() передать желаемый / ожидаемый часовой пояс, который будет назначен. Используйте класс DateTimeZone.

DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );

Этот класс содержит константу для часового пояса UTC .

DateTime now = DateTime.now( DateTimeZone.UTC );

Если вы действительно хотите использовать текущий часовой пояс JVM по умолчанию, сделайте явный вызов, чтобы ваш код самодокументировался.

DateTimeZone zoneDefault = DateTimeZone.getDefault();

ISO 8601

Читайте о ISO 8601 форматах. И java.time, и Joda-Time используют разумные форматы этого стандарта в качестве значений по умолчанию как для разбора, так и для генерации строк.


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

83 голосов
/ 14 июля 2011

Это определенно возвращает время UTC: как объекты String и Date!

static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

public static Date getUTCdatetimeAsDate() {
    // note: doesn't check for null
    return stringDateToDate(getUTCdatetimeAsString());
}

public static String getUTCdatetimeAsString() {
    final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    final String utcTime = sdf.format(new Date());

    return utcTime;
}

public static Date stringDateToDate(String StrDate) {
    Date dateToReturn = null;
    SimpleDateFormat dateFormat = new SimpleDateFormat(DATEFORMAT);

    try {
        dateToReturn = (Date)dateFormat.parse(StrDate);
    }
    catch (ParseException e) {
        e.printStackTrace();
    }

    return dateToReturn;
}
65 голосов
/ 16 марта 2010
    Calendar c = Calendar.getInstance();
    System.out.println("current: "+c.getTime());

    TimeZone z = c.getTimeZone();
    int offset = z.getRawOffset();
    if(z.inDaylightTime(new Date())){
        offset = offset + z.getDSTSavings();
    }
    int offsetHrs = offset / 1000 / 60 / 60;
    int offsetMins = offset / 1000 / 60 % 60;

    System.out.println("offset: " + offsetHrs);
    System.out.println("offset: " + offsetMins);

    c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
    c.add(Calendar.MINUTE, (-offsetMins));

    System.out.println("GMT Time: "+c.getTime());
50 голосов
/ 08 ноября 2010

На самом деле не время, но его представление можно изменить.

SimpleDateFormat f = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));

Время одинаково в любой точке Земли, но наше восприятие времени может быть различным в зависимости от местоположения.

17 голосов
/ 06 апреля 2010

Календарь aGMTCalendar = Calendar.getInstance (TimeZone.getTimeZone ("GMT")); Тогда все операции, выполняемые с использованием объекта aGMTCalendar, будут выполняться с часовым поясом GMT, и для него не будет применяться летнее время или фиксированные смещения

Неправильно!

Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
aGMTCalendar.getTime(); //or getTimeInMillis()

и

Calendar aNotGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));aNotGMTCalendar.getTime();

вернется в то же время. То же самое для

new Date(); //it's not GMT.
16 голосов
/ 26 октября 2013

Этот код печатает текущее время UTC.

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


public class Test
{
    public static void main(final String[] args) throws ParseException
    {
        final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
        f.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println(f.format(new Date()));
    }
}

Результат

2013-10-26 14:37:48 UTC
13 голосов
/ 16 мая 2013

Это работает для получения UTC миллисекунд в Android.

Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);  
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;
10 голосов
/ 22 мая 2012

Вот что кажется неправильным в ответ Джона Скита . Он сказал:

java.util.Date всегда в UTC. Что заставляет вас думать, что это по-местному время? Я подозреваю, что проблема в том, что вы отображаете это через экземпляр календаря, который использует местный часовой пояс, или, возможно, используя Date.toString(), который также использует местный часовой пояс.

Однако код:

System.out.println(new java.util.Date().getHours() + " hours");

указывает местное время, а не время по Гринвичу (UTC), без использования Calendar и вообще без SimpleDateFormat.

Вот почему кажется, что-то не так.

Собираем ответы, код:

System.out.println(Calendar.getInstance(TimeZone.getTimeZone("GMT"))
                           .get(Calendar.HOUR_OF_DAY) + " Hours");

показывает часы по Гринвичу вместо местных часов - обратите внимание, что отсутствует getTime.getHours(), поскольку это создаст объект Date(), который теоретически сохраняет дату в GMT, но возвращает часы в местном часовом поясе.

...