Как я могу получить текущую дату и время в UTC или GMT в Java?
Когда я создаю новый Date
объект, он инициализируется на текущее время, но в местном часовом поясе. Как узнать текущую дату и время в GMT?
34 ответа
java.util.Date
не имеет определенного часового пояса, хотя его значение чаще всего рассматривается по отношению к UTC. Что заставляет вас думать, что это по местному времени?
Чтобы быть точным: значение в пределах java.util.Date
количество миллисекунд, прошедших с эпохи Unix, которая произошла в полночь 1 января 1970 года по Гринвичу. Та же самая эпоха могла также быть описана в других часовых поясах, но традиционное описание в терминах UTC. Поскольку это число в миллисекундах с фиксированной эпохи, значение в java.util.Date
В любой конкретный момент во всем мире происходит то же самое, независимо от местного часового пояса.
Я подозреваю, что проблема в том, что вы отображаете его с помощью экземпляра Calendar, который использует местный часовой пояс, или, возможно, с помощью Date.toString()
который также использует местный часовой пояс, или SimpleDateFormat
экземпляр, который по умолчанию также использует местный часовой пояс.
Если это не проблема, пожалуйста, отправьте пример кода.
Однако я бы порекомендовал вам в любом случае использовать Joda-Time, который предлагает гораздо более понятный API.
ТЛ; др
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
- Joda времени
java.time (Java 8)
Java 8 предлагает отличный новый пакет java.time.* Для замены старых классов java.util.Date/Calendar.
Чтобы узнать текущее время в UTC/GMT, достаточно одной строки…
Instant instant = Instant.now();
Тот Instant
class является базовым строительным блоком в 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
Классы java.time определены JSR 310. Они были вдохновлены Joda-Time, но полностью перестроены.
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.
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()) );
Это определенно возвращает время UTC: как объекты String и Date!
static final String DATEFORMAT = "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(DATEFORMAT);
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;
}
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 f = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));
Время одинаково в любой точке Земли, но наше восприятие времени может быть различным в зависимости от местоположения.
Это работает для получения UTC миллисекунд в Android.
Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;
Календарь 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.
Этот код печатает текущее время 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
Джон Скит спрашивает:
@Downvoter: Хотите прокомментировать? Что именно неверно в моем ответе? - Джон Скит 26 октября 2009 года в 21:09
Я не Downvoter, но вот то, что кажется неправильным в этом ответе. Вы сказали:
java.util.Date
всегда в UTC. Что заставляет вас думать, что это по местному времени? Я подозреваю, что проблема в том, что вы отображаете его с помощью экземпляра Calendar, который использует местный часовой пояс, или, возможно, с помощью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, но возвращает часы в местном часовом поясе.
Если вам нужен объект 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));
Вот моя реализация TOUTC:
public static Date toUTC(Date date){
long datems = date.getTime();
long timezoneoffset = TimeZone.getDefault().getOffset(datems);
datems -= timezoneoffset;
return new Date(datems);
}
Вероятно, есть несколько способов улучшить это, но это работает для меня.
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));
Вы можете напрямую использовать это
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");
Ты можешь использовать:
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Тогда все операции, выполняемые с использованием объекта aGMTCalendar, будут выполняться с часовым поясом GMT и не будут применяться летнее время или фиксированные смещения. Я думаю, что предыдущий плакат верен, что объект Date() всегда возвращает GMT, пока вы не сделаете что-то с объектом даты, который будет преобразован в местный часовой пояс.
Вот еще один способ получить время по Гринвичу в формате 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());
С:
Calendar cal = Calendar.getInstance();
затем cal
иметь текущую дату и время.
Вы также можете получить текущую дату и время для часового пояса с помощью:
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));
Вы могли бы спросить cal.get(Calendar.DATE);
или другие постоянные Календаря о других деталях.
Дата и метка времени устарели в Java. Календарный класс это не так.
Вот другое предложение, чтобы получить объект 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));
}
Простая функция, которую вы можете использовать:
Изменить: в этой версии используются современные классы java.time.
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss z");
public static String getUtcDateTime() {
return ZonedDateTime.now(ZoneId.of("Etc/UTC")).format(FORMATTER);
}
Возвращаемое значение из метода:
26-03-2022 17:38:55 UTC
Оригинальная функция:
public String getUTC_DateTime() {
SimpleDateFormat dateTimeFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z");
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//gmt
return dateTimeFormat.format(new Date());
}
возврат вышеуказанной функции:
26-03-2022 08:07:21 UTC
Преобразование текущего 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
Просто чтобы сделать это проще, чтобы создать Date
в UTC
ты можешь использовать Calendar
:
Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Который создаст новый экземпляр для Calendar
используя "UTC" TimeZone
,
Если вам нужно Date
объект из этого календаря вы можете просто использовать getTime()
,
Пример кода для отображения системного времени в определенном часовом поясе и в определенном формате.
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
public static void main(String args[]){
LocalDate date=LocalDate.now();
System.out.println("Current date = "+date);
}
Текущая дата в UTC
Instant.now().toString().replaceAll("T.*", "");
Я делаю это так, когда мне нужно вывести объект Date , что обычно бывает, когда вам нужно сохранить дату в базе данных SQL, и я хочу, чтобы она была в формате UTC. Я просто вычитаю время смещения местного часового пояса.
ZonedDateTime now = ZonedDateTime.now();
Date nowUTC = new Date(1000 * (now.toEpochSecond() - now.getOffset().getTotalSeconds()));
--UPDATE Предложение Василия о более чистом способе получения того же результата будет
Date nowUTC = Date.from(ZonedDateTime.now().toInstant());
НО после тестирования этого в среде Java, отличной от UTC, я увидел, что результаты не совпадают. С кодом Василия Дата все еще находится в локальной зоне.
Это сработало для меня, возвращает метку времени в 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();
}
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
Вы можете изменить формат даты по мере необходимости.
Это моя реализация:
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();
}
Если вы хотите избежать разбора даты и просто хотите использовать метку времени в GMT, вы можете использовать:
final Date gmt = new Timestamp(System.currentTimeMillis()
- Calendar.getInstance().getTimeZone()
.getOffset(System.currentTimeMillis()));
Проще говоря. Объект календаря хранит информацию о часовом поясе, но при выполнении cal.getTime() информация о часовом поясе будет потеряна. Поэтому для преобразования часовых поясов я советую использовать классы DateFormat...