¿Cómo puedo obtener la fecha y hora actual en UTC o GMT en Java?

Cuando creo un nuevo objeto Date , se inicializa a la hora actual pero en la zona horaria local. ¿Cómo puedo obtener la fecha y hora actual en GMT?

java.util.Date no tiene un huso horario específico, aunque su valor se piensa más comúnmente en relación con UTC. ¿Qué te hace pensar que es hora local?

Para ser precisos: el valor dentro de un java.util.Date es el número de milisegundos desde la época de Unix, que ocurrió a la medianoche del 1 de enero de 1970, UTC. La misma época también podría describirse en otras zonas horarias, pero la descripción tradicional es en términos de UTC. Como se trata de una cantidad de milisegundos desde una época fija, el valor dentro de java.util.Date es el mismo en todo el mundo en cualquier instante en particular, independientemente de la zona horaria local.

Sospecho que el problema es que lo estás mostrando a través de una instancia de Calendar que usa la zona horaria local, o posiblemente usando Date.toString() que también usa la zona horaria local, o una instancia SimpleDateFormat , que, de forma predeterminada, también usa local zona horaria.

Si este no es el problema, publique un código de muestra.

Sin embargo, recomendaría que usas Joda-Time de todos modos, lo que ofrece una API mucho más clara.

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

tl; dr

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

Genera una cadena para representar ese valor:

 Instant.now().toString() 

2016-09-13T23: 30: 52.123Z

Detalles

Como dijo la respuesta correcta de Jon Skeet , un objeto java.util.Date no tiene zona horaria . Pero su implementación toString aplica el huso horario predeterminado de la JVM cuando genera la representación de cadena de ese valor de fecha y hora. Confusamente para el progtwigdor ingenuo, una Fecha parece tener un huso horario pero no lo tiene.

Las clases java.util.Date , juCalendar y java.text.SimpleDateFormat incluidas con Java son notoriamente problemáticas. Evítales. En su lugar, use cualquiera de estas bibliotecas de fecha y hora competentes:

  • paquete java.time. * en Java 8
  • Joda-Time

java.time (Java 8)

Java 8 trae un excelente nuevo paquete java.time. * Para suplantar las antiguas clases java.util.Date/Calendar.

Obtener la hora actual en UTC / GMT es un simple trazador de líneas …

 Instant instant = Instant.now(); 

Esa clase Instant es el bloque de construcción básico en java.time, que representa un momento en la línea de tiempo en UTC con una resolución de nanosegundos .

En Java 8, el momento actual se captura con una resolución de solo milisegundos. Java 9 trae una nueva implementación de Clock captura el momento actual hasta la capacidad máxima de nanosegundos de esta clase, dependiendo de la capacidad del hardware del reloj de su computadora host.

Su método toString genera una representación de cadena de su valor usando un formato ISO 8601 específico . Ese formato genera dígitos de cero, tres, seis o nueve dígitos ( milisegundos , microsegundos o nanosegundos ) según sea necesario para representar la fracción de segundo.

Si desea un formato más flexible, ajustes dentro o fuera de varias zonas horarias u otras características adicionales, aplique una zona horaria (objeto ZoneId ) para obtener un ZonedDateTime . La zona horaria puede ser para UTC o cualquier otra zona horaria. La subclase de ZoneId , ZoneOffset contiene una constante para UTC .

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

Volcado a la consola …

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

Cuando se ejecuta …

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

Las clases java.time están definidas por JSR 310 . Fueron inspirados por Joda-Time, pero están completamente remodelados.

Joda-Time

ACTUALIZACIÓN: El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Utilizando la biblioteca de código abierto de código abierto de terceros de Joda-Time , puede obtener la fecha actual en una sola línea de código.

Joda-Time inspiró las nuevas clases java.time. * En Java 8, pero tiene una architecture diferente. Puede usar Joda-Time en versiones anteriores de Java. Joda-Time continúa funcionando en Java 8 y continúa manteniéndose activamente (a partir de 2014). Sin embargo, el equipo de Joda-Time recomienda la migración a java.time.

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

Código de ejemplo más detallado (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 ); 

Volcado a la consola …

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

Cuando se ejecuta …

 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 

Para obtener más código de ejemplo haciendo un trabajo de zona horaria, vea mi respuesta a una pregunta similar.

Zona horaria

Te recomiendo que siempre especifiques un huso horario en lugar de depender implícitamente de la zona horaria predeterminada actual de la JVM (¡que puede cambiar en cualquier momento!). Tal confianza parece ser una causa común de confusión y errores en el trabajo de fecha y hora.

Cuando llame now() pase la zona horaria deseada / esperada para ser asignada. Use la clase DateTimeZone .

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

Esa clase contiene una constante para la zona horaria UTC .

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

Si realmente desea utilizar la zona horaria predeterminada actual de la JVM, realice una llamada explícita para que su código sea autodidacta.

 DateTimeZone zoneDefault = DateTimeZone.getDefault(); 

ISO 8601

Lea acerca de los formatos ISO 8601 . Tanto java.time como Joda-Time usan los formatos sensibles de ese estándar como sus valores predeterminados para analizar y generar cadenas.


En realidad, java.util.Date tiene un huso horario, enterrado bajo capas de código fuente. Para la mayoría de los propósitos prácticos, ese huso horario se ignora. Entonces, como taquigrafía, decimos que java.util.Date no tiene zona horaria. Además, esa zona horaria enterrada no es la utilizada por el método Date toString ; ese método usa la zona horaria predeterminada actual de la JVM. Razón de más para evitar esta clase confusa y apegarse a Joda-Time y java.time.

Esto definitivamente devuelve la hora UTC: ¡como objetos String y 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()); 

En realidad no es tiempo, pero su representación podría cambiarse.

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

El tiempo es el mismo en cualquier punto de la Tierra, pero nuestra percepción del tiempo podría ser diferente según la ubicación.

Calendario aGMTCalendar = Calendar.getInstance (TimeZone.getTimeZone (“GMT”)); Luego, todas las operaciones realizadas con el objeto aGMTCalendar se realizarán con la zona horaria GMT y no tendrán el horario de verano ni se aplicarán las compensaciones fijas

¡Incorrecto!

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

y

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

regresará al mismo tiempo. Idem para

 new Date(); //it's not GMT. 

Este código imprime la hora actual 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())); } } 

Resultado

 2013-10-26 14:37:48 UTC 

Esto funciona para obtener milisegundos UTC en Android.

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

Jon Skeet pregunta:

@Downvoter: ¿Te importa comentar? ¿Qué es exactamente incorrecto en mi respuesta? – Jon Skeet 26 de octubre de 2009 a las 21:09

No soy el Devaluador, pero esto es lo que parece ser incorrecto en esa respuesta. Tu dijiste:

java.util.Date siempre está en UTC. ¿Qué te hace pensar que es hora local? Sospecho que el problema es que lo estás mostrando a través de una instancia de Calendar que usa la zona horaria local, o posiblemente usando Date.toString() que también usa la zona horaria local.

Sin embargo, el código:

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

da las horas locales, no GMT (horas UTC), sin usar Calendar ni SimpleDateFormat .

Es por eso que parece que algo es incorrecto.

Juntando las respuestas, el código:

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

muestra las horas GMT en lugar de las horas locales; tenga en cuenta que getTime.getHours() falta porque eso crearía un objeto Date() , que teóricamente almacena la fecha en GMT, pero devuelve las horas en la zona horaria local.

Si desea un objeto Date con campos ajustados para UTC, puede hacerlo así con 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)); 

Puedes usar:

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

A continuación, todas las operaciones realizadas con el objeto aGMTCalendar se realizarán con la zona horaria GMT y no se aplicará el horario de verano o las compensaciones fijas. Creo que el poster anterior es correcto que el objeto Date () siempre devuelve un GMT, no es hasta que vas a hacer algo con el objeto date que se convierte a la zona horaria local.

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

Con:

 Calendar cal = Calendar.getInstance(); 

Entonces cal tiene la fecha y hora actual.
También podría obtener la fecha y hora actual para la zona horaria con:

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

Puede preguntar cal.get(Calendar.DATE); u otra constante del calendario sobre otros detalles.
Date y Timestamp están en desuso en Java. Clase calendario no es.

Aquí hay otra sugerencia para obtener un objeto 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)); } 

Aquí hay otra forma de obtener tiempo GMT en formato de cadena

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

Puedes usar esto directamente

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

Para simplificar esto, para crear una Date en UTC puede usar Calendar :

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

Lo cual construirá una nueva instancia para Calendar utilizando el TimeZone “UTC”.

Si necesita un objeto Date de ese calendario, puede usar getTime() .

Código de muestra para procesar la hora del sistema en una zona horaria específica y un formato específico.

 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){ //< +/->: // 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 az 'on' MM/dd/yyyy")); System.out.println("---------------------------------------------"); // Alternate format System.out.println(my_time_in("America/Los_Angeles", "'at' HH:mm az 'on' MM/dd/yyyy") ); System.out.println(my_time_in("America/Buenos_Aires", "'at' HH:mm az '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); } } 

Salida

 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 

Conversión de DateTime actual en 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 

Esto funcionó para mí, ¡devuelve la marca de tiempo en 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 static void main(String args[]){ LocalDate date=LocalDate.now(); System.out.println("Current date = "+date); } 

Para decirlo simple. Un objeto de calendario almacena información sobre la zona horaria, pero cuando realiza cal.getTime (), la información de la zona horaria se perderá. Entonces, para las conversiones de Timezone, les aconsejaré que usen las clases DateFormat …

Utilice esta clase para obtener siempre la hora UTC correcta de un servidor NTP en línea:

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

Y úsala con:

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

Si necesita la hora UTC "ahora" como función de uso de 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 ""; } } 

y úsala con:

 String UTC_DateTime = get_UTC_Datetime_from_timestamp(now); 

Aquí está mi implementación de toUTC:

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

Probablemente haya varias maneras de mejorarlo, pero funciona para mí.

esta es mi implementación:

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

Si está utilizando la hora joda y quiere la hora actual en milisegundos sin su desplazamiento local , puede usar esto:

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

Si desea evitar el análisis de la fecha y solo desea una marca de tiempo en GMT, puede usar:

 final Date gmt = new Timestamp(System.currentTimeMillis() - Calendar.getInstance().getTimeZone() .getOffset(System.currentTimeMillis())); 
 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)); } } 

Salida:

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

Puede cambiar el formato de fecha según sea necesario.