studio - ¿Cómo puedo obtener la fecha y hora actual en UTC o GMT en Java?
obtener zona horaria java (30)
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 se aplicarán el horario de verano ni 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();
Volverá al mismo tiempo. Idem para
new Date(); //it''s not GMT.
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?
tl; dr
Instant.now() // Capture the current moment in UTC.
Generar 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 la zona horaria predeterminada de la JVM al generar la representación de cadena de ese valor de fecha y hora. Confusamente con el programador ingenuo, una fecha parece tener una zona horaria pero no la tiene.
Las clases java.util.Date
, juCalendar
y java.text.SimpleDateFormat
incluidas en Java son notoriamente problemáticas. Evítales. En su lugar, utilice cualquiera de estas bibliotecas de fecha y hora competentes:
- java.time.* en Java 8
- Joda-Time
java.time (Java 8)
Java 8 trae un excelente nuevo paquete java.time. * Para reemplazar las antiguas clases java.util.Date/Calendar.
Obtener la hora actual en UTC / GMT es un sencillo de una sola línea ...
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 nanoseconds .
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 total de nanosegundos de esta clase, dependiendo de la capacidad del hardware del reloj de su computadora host.
El método toString
genera una representación de cadena de su valor utilizando un formato ISO 8601 específico . Ese formato genera cero, tres, seis o nueve dígitos dígitos ( milliseconds , microseconds o nanoseconds ) según sea necesario para representar la fracción de segundo.
Si desea un formato más flexible u otras funciones adicionales, aplique un offset-from-UTC de cero, para UTC ( ZoneOffset.UTC
constant ) para obtener un OffsetDateTime
.
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );
Volcar 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 rediseñados.
Tiempo de joda
ACTUALIZACIÓN: El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Al utilizar la biblioteca de código abierto de terceros de Joda-Time , puede obtener la fecha y hora actual en una sola línea de código.
Joda-Time inspiró las nuevas clases java.time. * En Java 8, pero tiene una arquitectura diferente. Puedes usar Joda-Time en versiones anteriores de Java. Joda-Time continúa trabajando en Java 8 y se mantiene 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 );
Volcar 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 que hace el trabajo de zona horaria, vea mi respuesta a una pregunta similar.
Zona horaria
Le recomiendo que siempre especifique una zona horaria en lugar de confiar implícitamente en 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.
Al llamar now()
pase la zona horaria deseada / esperada que se asignará. Usa la clase DateTimeZone
.
DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );
Esa clase tiene 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, haga una llamada explícita para que su código se autodocumente.
DateTimeZone zoneDefault = DateTimeZone.getDefault();
ISO 8601
Lea sobre los formatos ISO 8601 . Tanto java.time como Joda-Time utilizan los formatos sensibles de ese estándar como sus valores predeterminados para analizar y generar cadenas.
† En realidad, java.util.Date tiene una zona horaria, profundamente oculta bajo las capas del código fuente. Para la mayoría de los propósitos prácticos, esa zona horaria se ignora. Entonces, como taquigrafía, decimos que java.util.Date no tiene zona horaria. Además, esa zona horaria no es la utilizada por el método toString
de Date; ese método utiliza la zona horaria predeterminada actual de la JVM. Más razón para evitar esta clase confusa y seguir con Joda-Time y java.time.
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 hay varias formas de mejorarlo, pero funciona para mí.
Aquí hay otra manera de obtener la hora 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());
Aquí otra sugerencia para obtener un objeto de marca de tiempo 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));
}
Código de ejemplo para representar 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){
//<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);
}
}
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
Con:
Calendar cal = Calendar.getInstance();
Entonces cal
tiene la fecha y hora actual.
También puede obtener la Fecha y Hora actuales para la zona horaria con:
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));
Usted podría pedir cal.get(Calendar.DATE);
u otra constante de calendario sobre otros detalles.
La fecha y la marca de tiempo están en desuso en Java. La clase de calendario no lo es.
En realidad no es tiempo, pero su representación podría ser cambiada.
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.
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 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;
}
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();
}
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: ¿Quieres comentar? ¿Qué es exactamente incorrecto en mi respuesta? - Jon Skeet, 26 de octubre de 2009 a las 21:09
No soy el Downvoter, pero aquí está lo que parece ser incorrecto en esa respuesta. Tu dijiste:
java.util.Date
siempre está en UTC. ¿Qué te hace pensar que está en hora local? Sospecho que el problema es que lo está mostrando a través de una instancia de Calendario que usa la zona horaria local, o posiblemente usaDate.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
en absoluto.
Por eso 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()
porque crearía un objeto Date()
, que en teoría almacena la fecha en GMT, pero devuelve las horas en la zona horaria local.
Para ponerlo 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á. Así que para las conversiones de zonas horarias, le aconsejaré que use las clases de DateFormat ...
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())+"");
Puedes usar:
Calendar 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 se aplicarán el horario de verano ni las compensaciones fijas. Creo que el póster anterior es correcto en cuanto a que el objeto Date () siempre devuelve un GMT, no es hasta que se hace algo con el objeto date que se convierte a la zona horaria local.
Si desea evitar analizar la fecha y solo desea una marca de hora en GMT, puede usar:
final Date gmt = new Timestamp(System.currentTimeMillis()
- Calendar.getInstance().getTimeZone()
.getOffset(System.currentTimeMillis()));
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));
Si está utilizando el tiempo de joda y desea la hora actual en milisegundos sin su desplazamiento local , puede usar esto:
long instant = DateTimeZone.UTC.getMillisKeepLocal(DateTimeZone.getDefault(), System.currentTimeMillis());
Solo para hacer esto más simple, para crear una Date
en UTC
puede usar el Calendar
:
Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Lo que construirá una nueva instancia para el Calendar
utilizando la zona TimeZone
"UTC".
Si necesita un objeto Date
de ese calendario, podría usar getTime()
.
Use el paquete java.time e incluya el siguiente código
ZonedDateTime now = ZonedDateTime.now( ZoneOffset.UTC );
o
LocalDateTime now2 = LocalDateTime.now( ZoneOffset.UTC );
Dependiendo de su necesidad de aplicación.
Utilice esta Clase para obtener la hora UTC correcta desde 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 utilízalo 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 usarlo con:
String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);
esta es mi implementacion
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();
}
java.util.Date
no tiene una zona horaria específica, aunque su valor se piensa más comúnmente en relación con UTC. ¿Qué te hace pensar que está en hora local?
Para ser precisos: el valor dentro de 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á mostrando a través de una instancia de Calendario que usa la zona horaria local, o posiblemente usa Date.toString()
que también usa la zona horaria local, o una instancia de SimpleDateFormat
, que, de forma predeterminada, también usa zona horaria.
Si este no es el problema, por favor publique un código de ejemplo.
Sin embargo, recomendaría que use Joda-Time todos modos, que ofrece una API mucho más clara.
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
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-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));
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()) );
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.
public static void main(String args[]){
LocalDate date=LocalDate.now();
System.out.println("Current date = "+date);
}