Как я могу получить текущую дату и время в формате UTC или GMT на Java?

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

Я знаю, что эти темы полностью обсуждаются, но я обнаружил, что пакет commons-lang действительно хорошо справляется с этими общими проблемами Java. commons.apache.org/lang/api-2.5/org/apache/commons/lang/time Ознакомьтесь с различными пакетами, которые у них есть.

user130532 26.03.2012 19:44

Какое местное время вы хотите и с какой точностью. Большинство часовых поясов определены относительно всемирного координированного времени с фиксированным смещением, измеряемым в SI секундах, но взаимосвязь между GMT, основанным на наблюдении за Солнцем, и секундами (немного) переменной длины более сложна. Они отличаются на 0,9 секунды.

mc0e 27.02.2017 07:34

Date не поддерживает часовой пояс, поэтому "но в местном часовом поясе" неверно (или, в лучшем случае, неточно). См. Все о java.util.Date.

Ole V.V. 04.07.2018 08:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
515
3
950 471
30
Перейти к ответу Данный вопрос помечен как решенный

Ответы 30

Ответ принят как подходящий

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

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

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

Если проблема не в этом, опубликуйте образец кода.

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

Я использовал новый объект Date () и вставил его в таблицу БД. БД - это MySQL, и когда я использую функцию UTC_TIMESTAMP () в MySQL, она работает правильно, но когда я вставляю значение новой даты (), оно вставляется в мой локальный часовой пояс.

Behrang 21.11.2008 16:58

Тогда это, вероятно, проблема с драйвером. Возможно, вам потребуется установить соединение в формате UTC или что-то в этом роде. Я видел подобные проблемы раньше, но проблема не в java.util.Date.

Jon Skeet 21.11.2008 17:07

Спасибо. Ты прав. Я просмотрел свойства подключения mysql, но не смог найти правильную конфигурацию. Я задал другой вопрос: как сохранить java.util.Date в поле метки времени MySQL в часовом поясе UTC / GMT? Если можете, пожалуйста, помогите мне в этом.

Behrang 21.11.2008 19:06

К сожалению, я не знаю - прошло много времени с тех пор, как я сделал Любые JDBC, и ни одного в MySQL, никогда ...

Jon Skeet 21.11.2008 19:10

Behrang, согласно stackoverflow.com/questions/4123534/…, драйвер MySQL JDBC преобразует данный java.util.Timestamp (или java.util.Date) в часовой пояс сервера.

Derek Mahar 08.12.2010 00:02

@Мистер. Кошка: Как вы это определяете? Это путем записи System.out.println(new Date())? Если это так, вы должны знать, что это метод toString(), который применяет часовой пояс там ... если это не так, просьба сообщить более подробную информацию.

Jon Skeet 07.09.2011 17:59

В документации Date говорится: «Хотя класс Date предназначен для отображения всемирного координированного времени (UTC), он может не отражать это точно, в зависимости от среды хоста виртуальной машины Java». Например, на моем компьютере или телефоне с Android, когда я инициализирую новый объект Date, устанавливается значение GMT, а не UTC. Никакого отрицательного голоса с моей стороны, может я неправильно понял.

Ovidiu Latcu 17.05.2012 17:04

@OvidiuLatcu: Это просто говорит о том, что точность системных часов может быть ограничена. Я подозреваю, что вы имеете в виду результаты Date.toString(), которые, опять же, связаны с отображением. Но в любом случае GMT ​​и UTC фактически находятся в одном часовом поясе. (Есть некоторые очень тонкие несоответствия, но здесь не о чем беспокоиться.)

Jon Skeet 31.05.2012 09:11

@JonSkeet Не могли бы вы указать мне на какой-нибудь ресурс, который помогает понять, почему считается, что Joda time дает гораздо более ясный api?

Geek 06.11.2012 14:34

@Geek: у меня нет ресурса под рукой, но тот факт, что Joda Time поддерживает неизменяемые типы и имеет гораздо более широкий диапазон типов классифицировать, является хорошим началом. API даты и календаря - это просто ужасный.

Jon Skeet 06.11.2012 14:36

@Jon Skeet Значит, вы хотите сказать, что new Date (). GetTime () вернет миллисекунды UTC независимо от tz? Что заставляет вас думать, что Дата находится в формате UTC?

Kanagavelu Sugumar 28.12.2012 15:00

@KanagaveluSugumar: Гм, документация? В документации для getTime() указано: «Возвращает количество миллисекунд с 1 января 1970 года, 00:00:00 по Гринвичу, представленное этим объектом Date».

Jon Skeet 28.12.2012 15:08

@JonSkeet Спасибо, Джон. Если date.toString () выводит «Tue Dec 25 10:00:00 IST 2012», date.getTime () выводит 1356409800000; Тогда date.getime () - это то же самое «Вт 25 декабря 10:00:00» в миллисекундах или «Вт 25 декабря 04:30:00» (IST-5.30 = GMT)? Пожалуйста, помогите мне понять.

Kanagavelu Sugumar 28.12.2012 16:19

@KanagaveluSugumar: toString() всегда использует часовой пояс по умолчанию. date.getTime() определенно возвращает миллисекунды с эпохи Unix в UTC. Наиболее точно будет сказать, что у Date вообще нет часового пояса - это только момент времени, который можно рассматривать в нескольких часовых поясах. Но когда вы создаете экземпляр, не зависит от вашего часового пояса.

Jon Skeet 28.12.2012 16:33

@JonSkeet Большое спасибо. Не могли бы вы рассказать мне, как будет вести себя java.sql.TimeStamp (). Здесь также нет часового пояса? а ts.toString возьмет localTimezone ()? а ts.getTime () будет в UTC?

Kanagavelu Sugumar 28.12.2012 17:02

@KanagaveluSugumar: Сейчас мы далеко от исходного вопроса. Задайте вопрос новый после tinyurl.com/so-list

Jon Skeet 28.12.2012 17:26

@JonSkeet stackoverflow.com/questions/14070572/…

Kanagavelu Sugumar 28.12.2012 17:54

Это немного придирчиво, но преобразование времени / даты - нескончаемый источник путаницы для людей, которые только начинают с ними разбираться, поэтому я хотел указать на это. JonSkeet sprach: «date.getTime () определенно возвращает миллисекунды с эпохи Unix в UTC». Здесь "in UTC" является избыточным. Эпоха наступила, когда в Гринвиче (и в других местах) была полночь. В любой момент "new Date (). GetTime ()" где угодно на Земле должен дать вам то же самое число. Это одна из тех редких частей твердой почвы, которые вы можете выдержать в этой странной вселенной календарных преобразований.

Jemenake 01.05.2013 19:03

@Jemenake: На самом деле этого не произошло, когда в Гринвиче была полночь, потому что в Великобритании в то время было UTC + 1. Просто одна из странностей истории. Но я понимаю вашу точку зрения - лучше сказать «new Date (). GetTime () возвращает миллисекунды с эпохи Unix, которая была в полночь в начале 1 января 1970 года по всемирному координированному времени». Таким образом, UTC является частью привязки эпохи к конкретному моменту времени, а не частью результата.

Jon Skeet 01.05.2013 19:05

Правильный фон, но ответ кода здесь stackoverflow.com/a/5236123/1643558 Создайте SDF - часовой пояс UTC, отформатируйте дату, используя это. Шаблоны SDF - docs.oracle.com/javase/7/docs/api/java/text/…

tgkprog 19.08.2014 15:43

@tgkprog: вы предполагаете, что OP хочет строку. Нет никаких указаний на то, что это так.

Jon Skeet 19.08.2014 15:45

Строка или нет - этот ответ говорит более лаконично. Прочтите сначала свою, затем эту, затем снова свою, и это будет иметь больше смысла. некоторые люди лучше разбираются в коде.

tgkprog 19.08.2014 16:48
Date dt2 = new Date();System.out.println(" Hr " + dt2.getHours() + ", tz offset :" + dt2.getTimezoneOffset()); Запуск этого кода показывает мне местный час (час UTC +5,5 часа) и смещение часового пояса sas -330, что является правильным местным временем, поскольку я нахожусь в Индии. Поэтому, по-видимому, нужно изменить время объекта Date, чтобы получить UTC
tgkprog 19.08.2014 16:56

@tgkprog: Вы читали документацию по устаревшим методам, которые вы вызываете? (Примечание: «как интерпретируется в местном часовом поясе».) Ваш вывод о необходимости изменения содержимого Date для получения UTC полностью неверен.

Jon Skeet 19.08.2014 17:02

Хм, мне это нужно. Не хочу использовать Джоду. Не требуется интернационализация, поэтому мысль может игнорировать устаревшие классы Date (в нем говорится, что они устарели из-за невозможности интернационализации). Просто нужно текущее время по Гринвичу. так что используйте новый GreogorianCalender () ИЛИ? Что-то в Java 6. Спасибо, что уделили время, кстати:)

tgkprog 20.08.2014 19:56

Требуется это == требуется время в формате UTC

tgkprog 21.08.2014 00:56

@tgkprog: я предлагаю вам задать новый вопрос с вашими точными требованиями, что вы пробовали и т.д. На данный момент мы не знаем, действительно ли вы ищете текстовое представление, целочисленные значения, чтобы вы могли протестировать такие вещи, как "Это август?" и т.д. И вы абсолютно не должен игнорируете устаревание методов Date - интернационализация - лишь часть того, что с ними не так, хотя это один из симптомов того факта, что он всегда использует часовой пояс системы по умолчанию. Плохая документация :(

Jon Skeet 21.08.2014 01:09

Получил ответ от stackoverflow.com/questions/20482267/… long to milli - установите Calendar. В вопросе cal.setTimeInMillis (long);

tgkprog 21.08.2014 20:48

@tgkprog: Хорошо, я рад, что это помогло вам, даже если вы никогда толком не объясняли свою проблему ...

Jon Skeet 21.08.2014 20:49

Я понимаю, о чем спрашивал ОП. Сказать, что в JRE нет часового пояса, я не думаю, что это правильно. У него есть TZ локальной машины, на которой он работает. JRE получает время от базовой ОС, которая обычно устанавливается на локальную TZ. Хотя JRE знает об этом TZ, она возвращает локальное время ОС в 'System.currentTimeMillis ()' docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/‌… OP спрашивал, как они переводят это местное время обратно в UTC. Этот класс может помочь для этого docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html

Eurospoofer 16.03.2017 08:01

@Eurospoofer: Где кто-то сказал, что в JRE нет часового пояса? Ваш комментарий - единственное место, где "JRE" появилось в этом вопросе (когда я начинаю добавлять этот комментарий). Значение java.util.Date не имеет часового пояса, но это совершенно другое. И нет, System.currentTimeMillis() отражает местное время в нет - оно отражает количество миллисекунд, прошедших с эпохи Unix, а нет зависит от часового пояса. Документы, на которые вы ссылаетесь, просто говорят, что получение значения из системных часов зависит от ОС.

Jon Skeet 16.03.2017 12:25

С:

Calendar cal = Calendar.getInstance();

Тогда cal будет иметь текущую дату и время. Вы также можете получить текущую дату и время для часового пояса с помощью:

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

Вы можете спросить cal.get(Calendar.DATE); или другую константу Календаря о других деталях. Дата и отметка времени в Java устарели. Класс календаря это не так.

Некоторые методы и конструкторы Date и Timestamp устарели, но сами классы - нет.

Powerlord 21.11.2008 16:19

Вы можете использовать:

Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

Тогда все операции, выполняемые с использованием объекта aGMTCalendar, будут выполняться с часовым поясом GMT и не будут применять летнее время или фиксированные смещения. Я думаю, что предыдущий плакат верен в том, что объект Date () всегда возвращает время по Гринвичу, пока вы не сделаете что-то с объектом даты, который он преобразует в местный часовой пояс.

    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());
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()) );

Почему вы выполняете синтаксический анализ с помощью dateFormatLocal после использования формата dateFormatGmt ... не имеет смысла, читая его. Я уверен, что это работает, но просто интересно?

MindWire 16.06.2012 01:20

setTimeZone сделал это (я думаю, вы также можете использовать getTimeZone ("UTC") то же самое, что и GMT?)

rogerdpack 06.02.2013 04:05

но время зависит от установленного времени устройства. Если пользователь установил неправильное время на своем устройстве, вы получите неправильное время в формате UTC. Исправьте меня, если ошибаюсь

Basavaraj Hampali 21.08.2013 20:48

@BasavarajHampali, но в современном мире большинство устройств подключены к Интернету, что исправляет неправильное время

Akshat Agarwal 30.10.2013 19:18

Нет разницы во времени между всемирным координированным временем (UTC) и средним временем по Гринвичу (GMT).

slott 16.12.2014 13:11

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

Eurospoofer 16.03.2017 08:10

На данный момент UTC и GMT могут быть взаимозаменяемыми, но, выражаясь языком Java, GMT «устарело» и может не синхронизироваться с UTC в будущем.

JN01 08.05.2017 14:35

Среднее время по Гринвичу (GMT) часто заменяют или путают с всемирным координированным временем (UTC). Но GMT - это часовой пояс, а UTC - стандарт времени. timeanddate.com/time/gmt-utc-time.html

axiopisty 20.10.2018 02:00

Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); Then all operations performed using the aGMTCalendar object will be done with the GMT time zone and will not have the daylight savings time or fixed offsets applied

Неправильный!

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.

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

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

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

Ага, красивое и чистое решение. Меня просто беспокоит, неэффективно ли создать новый объект Date вместо того, чтобы просто получить экземпляр Calendar?

Beemo 06.10.2015 17:53

Он будет оптимизирован JVM, а HotSpot выполнит максимально эффективный код x86.

Antonio 07.10.2015 07:49

Верно, один раз, но много презентаций, в зависимости от места.

Sully 30.11.2020 21:20
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));

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

akjoshi 04.12.2012 11:18

зависит ли этот метод от календаря устройства?

Arnold Brown 09.11.2018 07:25

Это определенно возвращает время 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;
}

В своем ответе я забыл показать, как определяется DATEFORMAT: static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";

Someone Somewhere 26.07.2011 23:39

Пожалуйста, избегайте начинать имена методов с верхнего регистра в Java. См. Соглашения о кодировании Java для имен методов.

Florian Schrofner 02.05.2015 17:42

Поскольку меня перенаправили на этот ответ, Calling new Date() никогда не вернет правильное время в формате UTC, если время устройства неверно.

Sanoop Surendran 02.03.2017 11:55

зависит ли этот метод от календаря устройства?

Arnold Brown 09.11.2018 07:24

Одно замечание. Любое решение, которому нужно получить дату или метку времени в формате UTC, похоже, что ключ заключается в том, чтобы не повторно использовать SimpleDateFormat, а использовать его для преобразования UTC в строку, а затем создать другой UTC при преобразовании строки в дату или объект отметки времени. Я заметил, что если вы попытаетесь повторно использовать тот же SimpleDateFormat, то полученный объект Date / Timestamp вернется к местному часовому поясу вместо UTC.

Brian Begun 26.02.2019 07:28

Пример кода для отображения системного времени в определенном часовом поясе и в определенном формате.

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

public class TimZoneTest {
    public static void main (String[] args){
        //<GMT><+/-><hour>:<minutes>
        // Any screw up in this format, timezone defaults to GMT QUIETLY. So test your format a few times.

        System.out.println(my_time_in("GMT-5:00", "MM/dd/yyyy HH:mm:ss") );
        System.out.println(my_time_in("GMT+5:30", "'at' HH:mm a z 'on' MM/dd/yyyy"));

        System.out.println("---------------------------------------------");
        // Alternate format 
        System.out.println(my_time_in("America/Los_Angeles", "'at' HH:mm a z 'on' MM/dd/yyyy") );
        System.out.println(my_time_in("America/Buenos_Aires", "'at' HH:mm a z 'on' MM/dd/yyyy") );


    }

    public static String my_time_in(String target_time_zone, String format){
        TimeZone tz = TimeZone.getTimeZone(target_time_zone);
        Date date = Calendar.getInstance().getTime();
        SimpleDateFormat date_format_gmt = new SimpleDateFormat(format);
        date_format_gmt.setTimeZone(tz);
        return date_format_gmt.format(date);
    }

}

Выход

10/08/2011 21:07:21
at 07:37 AM GMT+05:30 on 10/09/2011
at 19:07 PM PDT on 10/08/2011
at 23:07 PM ART on 10/08/2011

Вы можете напрямую использовать это

SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");

Если вам нужен объект Date с полями, настроенными для UTC, вы можете сделать это следующим образом с помощью Джода Тайм:

import org.joda.time.DateTimeZone;
import java.util.Date;

...

Date local = new Date();
System.out.println("Local: " + local);
DateTimeZone zone = DateTimeZone.getDefault();
long utc = zone.convertLocalToUTC(local.getTime(), false);
System.out.println("UTC: " + new Date(utc));

Вы слишком много работаете. Джода-Тайм может сделать это в одной строке кода. См. мой собственный ответ по этому вопросу. Вызовите метод .toDateTime и передайте константу для часового пояса UTC.

Basil Bourque 08.11.2013 15:26

DateTime utcDate = новый DateTime (). ToDateTime (DateTimeZone.UTC)

Maciej Miklas 23.01.2014 11:58

Вот еще одно предложение получить объект метки времени GMT:

import java.sql.Timestamp;
import java.util.Calendar;

...

private static Timestamp getGMT() {
   Calendar cal = Calendar.getInstance();
   return new Timestamp(cal.getTimeInMillis()
                       -cal.get(Calendar.ZONE_OFFSET)
                       -cal.get(Calendar.DST_OFFSET));
}

Чтобы упростить задачу, для создания Date в UTC вы можете использовать Calendar:

Calendar.getInstance(TimeZone.getTimeZone("UTC"));

Будет построен новый экземпляр для Calendar с использованием «UTC» TimeZone.

Если вам нужен объект Date из этого календаря, вы можете просто использовать getTime().

Вызов getTime () для этого приводит к потере информации о часовом поясе и возврату местного времени.

RealCasually 19.09.2013 05:10

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

java.util.Date is always in UTC. What makes you think it's in local time? I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone.

Однако код:

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

дает местные часы, а не GMT ​​(часы UTC), без использования Calendar и вообще без SimpleDateFormat.

Поэтому кажется, что что-то не так.

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

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

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

Я раньше не видел этого ответа, но если вы прочитаете документацию по устаревшему методу Date.getHours(), он станет очень ясным: «Возвращаемое значение - это число (от 0 до 23), представляющее час в течение дня, который содержит или начинается с момент времени, представленный этим объектом Date, как интерпретируется в местном часовом поясе. " (Подчеркну мой.) Это метод getHours(), который интерпретирует значение в пределах местного часового пояса - это не часть состояния самого объекта Date.

Jon Skeet 11.05.2013 17:57

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

Basil Bourque 22.01.2014 05:14

Вот еще один способ получить время по Гринвичу в строковом формате.

String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z" ;
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String dateTimeString =  sdf.format(new Date());

Проще говоря. В объекте календаря хранится информация о часовом поясе, но при выполнении cal.getTime () информация о часовом поясе будет потеряна. Поэтому для преобразования часового пояса я посоветую использовать классы DateFormat ...

Это сработало для меня, возвращает метку времени в GMT!

    Date currDate;
    SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
    dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
    SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");

    long currTime = 0;
    try {

        currDate = dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
        currTime = currDate.getTime();
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

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

Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);  
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;

только смещение нужно вычесть?

tevch 27.07.2013 21:49
c.add(Calendar.MILLISECOND, (-utcOffset)), чтобы получить календарь с часовым поясом utc
Shanavas M 19.11.2015 17:18

Этот код печатает текущее время в формате 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

Используйте этот класс, чтобы всегда получать правильное время в формате UTC с онлайн-сервера NTP:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


class NTP_UTC_Time
{
private static final String TAG = "SntpClient";

private static final int RECEIVE_TIME_OFFSET = 32;
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;

private static final int NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_VERSION = 3;

// Number of seconds between Jan 1, 1900 and Jan 1, 1970
// 70 years plus 17 leap days
private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;

private long mNtpTime;

public boolean requestTime(String host, int timeout) {
    try {
        DatagramSocket socket = new DatagramSocket();
        socket.setSoTimeout(timeout);
        InetAddress address = InetAddress.getByName(host);
        byte[] buffer = new byte[NTP_PACKET_SIZE];
        DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);

        buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);

        writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);

        socket.send(request);

        // read the response
        DatagramPacket response = new DatagramPacket(buffer, buffer.length);
        socket.receive(response);          
        socket.close();

        mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);            
    } catch (Exception e) {
      //  if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
        return false;
    }

    return true;
}


public long getNtpTime() {
    return mNtpTime;
}


/**
 * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
 */
private long read32(byte[] buffer, int offset) {
    byte b0 = buffer[offset];
    byte b1 = buffer[offset+1];
    byte b2 = buffer[offset+2];
    byte b3 = buffer[offset+3];

    // convert signed bytes to unsigned values
    int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
    int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
    int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
    int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);

    return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
}

/**
 * Reads the NTP time stamp at the given offset in the buffer and returns 
 * it as a system time (milliseconds since January 1, 1970).
 */    
private long readTimeStamp(byte[] buffer, int offset) {
    long seconds = read32(buffer, offset);
    long fraction = read32(buffer, offset + 4);
    return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);        
}

/**
 * Writes 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
 */    
private void writeTimeStamp(byte[] buffer, int offset) {        
    int ofs =  offset++;

    for (int i=ofs;i<(ofs+8);i++)
      buffer[i] = (byte)(0);             
}

}

И используйте его с:

        long now = 0;

        NTP_UTC_Time client = new NTP_UTC_Time();

        if (client.requestTime("pool.ntp.org", 2000)) {              
          now = client.getNtpTime();
        }

Если вам нужно время UTC «сейчас» в качестве функции DateTimeString:

private String get_UTC_Datetime_from_timestamp(long timeStamp){

    try{

        Calendar cal = Calendar.getInstance();
        TimeZone tz = cal.getTimeZone();

        int tzt = tz.getOffset(System.currentTimeMillis());

        timeStamp -= tzt;

        // DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
        DateFormat sdf = new SimpleDateFormat();
        Date netDate = (new Date(timeStamp));
        return sdf.format(netDate);
    }
    catch(Exception ex){
        return "";
     }
    } 

и используйте его с:

String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);

Одной строкой <br/> <pre> <code> Calendar utcTime = Calendar.getInstance (). Add (Calendar.MILLISECOND, -time.getTimeZone (). GetOffset (time.getTimeInMillis ())); </ pre‌> </code>

Harun 28.11.2013 13:24

Да, но это вызывает локальное время устройства, которое может вручную измениться с пользователя на ложное DateTime.

Ingo 03.12.2013 18:59

Преобразование текущего DateTime в UTC:

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

DateTimeZone dateTimeZone = DateTimeZone.getDefault(); //Default Time Zone

DateTime currDateTime = new DateTime(); //Current DateTime

long utcTime = dateTimeZone.convertLocalToUTC(currDateTime .getMillis(), false);

String currTime = formatter.print(utcTime); //UTC time converted to string from long in format of formatter

currDateTime = formatter.parseDateTime(currTime); //Converted to DateTime in UTC

Вы делаете здесь слишком много работы. (a) Шаблон средства форматирования, который вы определяете, по умолчанию уже встроен в DateTime; просто вызовите toString в DateTime, чтобы получить этот строковый шаблон ISO 8601. (б) Слишком много кода для преобразования между часовыми поясами. Просто вызовите toDateTime и передайте объект часового пояса. Как это: myDateTime.toDateTime( DateTimeZone.UTC ). Для определенного часового пояса создайте экземпляр и передайте объект часового пояса на основе правильное имя, вызовите myDateTime.toDateTime( DateTimeZone.forID( "Asia/Tehran" ) ).

Basil Bourque 24.01.2014 01:48

это моя реализация:

public static String GetCurrentTimeStamp()
{
    Calendar cal=Calendar.getInstance();
    long offset = cal.getTimeZone().getOffset(System.currentTimeMillis());//if you want in UTC else remove it .
    return new java.sql.Timestamp(System.currentTimeMillis()+offset).toString();    
}

Если вы используете joda time и хотите текущее время в миллисекундах без вашего местного смещения, вы можете использовать это:

long instant = DateTimeZone.UTC.getMillisKeepLocal(DateTimeZone.getDefault(), System.currentTimeMillis());

Если вы хотите избежать синтаксического анализа даты и просто хотите указать временную метку в GMT, вы можете использовать:

final Date gmt = new Timestamp(System.currentTimeMillis()
            - Calendar.getInstance().getTimeZone()
                    .getOffset(System.currentTimeMillis()));

Вот моя реализация toUTC:

    public static Date toUTC(Date date){
    long datems = date.getTime();
    long timezoneoffset = TimeZone.getDefault().getOffset(datems);
    datems -= timezoneoffset;
    return new Date(datems);
}

Вероятно, есть несколько способов улучшить его, но у меня это работает.

public static void main(String args[]){
    LocalDate date=LocalDate.now();  
    System.out.println("Current date = "+date);
}
public class CurrentUtcDate 
{
    public static void main(String[] args) {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println("UTC Time is: " + dateFormat.format(date));
    }
}

Выход:

UTC Time is: 22-01-2018 13:14:35

При необходимости вы можете изменить формат даты.

Пожалуйста, не учите молодых пользоваться давно устаревшим и заведомо проблемным SimpleDateFormat. Сегодня у нас намного лучше в java.time, современный API даты и времени Java. И что вы предлагаете, чего еще нет в ответах Дэна, Антонио и других?

Ole V.V. 04.07.2018 08:11

(а) Как этот ответ повышает ценность десятков существующих ответов? (b) используемые здесь вызывающие беспокойство классы были вытеснены много лет назад современными классами java.time. Предлагать их использование в 2018 году - плохой совет.

Basil Bourque 04.07.2018 10:27

Используйте пакет java.time и включите ниже код -

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

или же

LocalDateTime now2 = LocalDateTime.now( ZoneOffset.UTC );

в зависимости от потребности вашего приложения.

(A) Если используется смещение (ZoneOffset), а не часовой пояс (ZoneId), OffsetDateTime более подходит, чем ZonedDateTime. (B) LocalDateTime не следует использовать для фиксации текущего момента, поскольку он не имеет понятия о часовом поясе или смещении от UTC. (C) Другие ранее существовавшие ответы охватили этот материал и сделали работу лучше. Я не понимаю, как этот ответ добавляет ценности.

Basil Bourque 02.11.2018 05:34

Текущая дата в UTC

Instant.now().toString().replaceAll("T.*", "");

Другие вопросы по теме