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


479

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


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

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

1
A Dateне содержит часовой пояс, поэтому «но в местном часовом поясе» не является правильным (или в лучшем случае неточным). См. Все о java.util.Date .
Ole VV

Ответы:


409

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

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

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

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

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


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

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

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

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

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

325

ТЛ; др

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постоянный ) получил a OffsetDateTime.

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

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

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

Когда беги…

now.toString(): 2014-01-21T23:42:03.522Z

Таблица типов даты и времени в Java, как современных, так и устаревших.


О java.time

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

Чтобы узнать больше, смотрите Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .

Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, соответствующий JDBC 4.2 или более поздней версии . Нет необходимости в строках, нет необходимости в java.sql.*классах.

Где взять классы java.time?

Таблица какой библиотеки java.time использовать с какой версией Java или Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь , такие как Interval, YearWeek, YearQuarter, и более .


Joda времени

ОБНОВЛЕНИЕ: Проект 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 используют разумные форматы этого стандарта в качестве значений по умолчанию для анализа и генерации строк.


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


2
DateTime.now().toDateTime(DateTimeZone.UTC)было то, что я искал! Спасибо!
Манагарм

1
@Managarm Вы можете сократить это до: DateTime nowUtc = DateTime.now ( DateTimeZone.UTC ) ;
Василий Бурк

Как получить это с помощью Pure Java 8 2014-01-21T15:34:29.933-08:00в примере, который вы использовалиnew org.joda.time.DateTime()
GOXR3PLUS

1
@ GOXR3PLUS ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ).truncatedTo( ChronoUnit.MILLIS ).toOffsetDateTime().toString() Мы получаем текущий момент для указанного часового пояса. Затем отрежьте любые микро / нанос. Затем мы конвертируем в наличие только простого смещения от UTC (количество часов-минут-секунд), а не полноценного часового пояса (история прошлых, настоящих и будущих изменений в смещении, используемом людьми конкретный регион). Наконец, мы генерируем текст, представляющий значение в OffsetDateTimeсоответствии со стандартным форматом ISO 8601, используемым по умолчанию в его toStringметоде.
Василий Бурк

Спасибо за то, что дали это подробное объяснение, также +1 для поддержки Android :) @BasilBourque
mochadwi

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

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

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

6
но время зависит от времени установки устройства. Если пользователь установил неправильное время на своем устройстве, то вы получите неправильный UTC. Исправьте меня, если я ошибаюсь
Басаварадж Хампали

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

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

86

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

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

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

время получения этого метода зависит от календаря устройства?
Арнольд Браун

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

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

52

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

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

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

17

Календарь 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.

17

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

14

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

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

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

c.add(Calendar.MILLISECOND, (-utcOffset))получить календарь с часовым поясом utc
Shanavas M

10

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

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

Тем не менее, код:

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

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

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

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

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

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


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

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

7

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

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

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

1
DateTime utcDate = new DateTime (). ToDateTime (DateTimeZone.UTC)
Мачей Миклас

6

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

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

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


6
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));

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

время получения этого метода зависит от календаря устройства?
Арнольд Браун

6

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

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

5

С:

Calendar cal = Calendar.getInstance();

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

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

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


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

5

Вот другое предложение, чтобы получить объект GMT Timestamp:

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

5

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

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

5

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

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

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


3

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

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

3

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

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

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

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


5
Вызов getTime () приводит к тому, что он теряет информацию о часовом поясе и возвращает местное время.
RealCasually

3

Преобразование текущего 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

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

2

Это сработало для меня, возвращает метку времени в 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();
    }

2

Используйте этот класс, чтобы получить правильное время 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>
Харун

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


1

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


1

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

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

1

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

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

0

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

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

0
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

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


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

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

0

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

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

или

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

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


(A) Если используется смещение ( ZoneOffset), а не часовой пояс ( ZoneId), то OffsetDateTimeболее подходящим, чем ZonedDateTime. (B) LocalDateTimeне должен использоваться для захвата текущего момента, так как он не имеет понятия часового пояса или смещения от UTC. (C) Другие ранее существовавшие Ответы охватили этот материал и сделали лучшую работу. Я не вижу, как этот ответ добавляет ценность.
Базилик Бурк
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.