❌ La Respuesta aceptada no es correcta ni útil.
✅ En cambio, la Respuesta de Ole V.V. resume correctamente las diferencias técnicas – para más detalles siga los enlaces a las páginas detalladas en Wikipedia.
Para los programadores que construyen aplicaciones orientadas a los negocios, el resultado es que UTC es el nuevo GMT. Se pueden utilizar los términos indistintamente, siendo la diferencia literalmente inferior a un segundo. Así que para todos los efectos prácticos en la mayoría de las aplicaciones, no hay ninguna diferencia.
Aquí hay algunos consejos más prácticos, con ejemplos de código.
Cadenas
Digamos que tengo la hora UTC como «02-01-2018 00:03» ¿significa eso que mi hora local de EEUU es «01-01-2018 18:00»?
Esa primera parte es un mal ejemplo, con la cadena de fecha-hora que carece de un indicador de su desplazamiento o zona.
Si una cadena indica un momento específico, debe indicar o bien una zona horaria (Continent/Region
nombre con formato) y/o un offset-from-UTC como un número de horas-minutos-segundos. Si la cadena está destinada a representar un momento en el mismo UTC, eso significa un offset-from-UTC de cero.
Para escribir esa cadena con un offset, se pueden aplicar varias convenciones. La mejor en la práctica es con las horas y los minutos junto con dos puntos, como +00:00
+05:30
, o -08:00
. El cero inicial y los dos puntos son opcionales, pero he visto que las bibliotecas se rompen al encontrar un valor como -0800
o -8
.
Zulú
Como atajo para un desplazamiento de cero, la letra Z
se utiliza comúnmente para significar el propio UTC. Se pronuncia Zulu
.
ISO 8601
Además, la mejor práctica para formatear la fecha-hora textualmente para la informática es utilizar los formatos estándar ISO 8601. Para una fecha-hora se utiliza el formato AAAA-MM-DDTHH:MM:SS±HH:MM:SS. El T
separa la parte de la fecha de la parte de la hora. Este formato tiene ventajas tales como ser ampliamente inequívoco, fácil de analizar por la máquina, fácil de leer por los seres humanos a través de las culturas. Otra ventaja es que la ordenación alfabética es también cronológica. El estándar acepta la abreviatura Z
también.
Así que tu ejemplo UTC time as "02-01-2018 00:03"
se expresa mejor como 2018-01-02T00:03Z
.
java.time
Tenga muy en cuenta que la mayoría de los lenguajes de programación, bibliotecas y bases de datos tienen un soporte muy pobre para el manejo de la fecha-hora, generalmente basado en una pobre comprensión de los temas de fecha-hora. El manejo de la fecha-hora es sorprendentemente complicado y difícil de dominar.
La única biblioteca decente que he encontrado son las clases java.time (ver Tutorial) incluidas en Java 8 y posteriores, y su predecesor el proyecto Joda-Time (también vagamente portado de Java a .Net en el proyecto Noda Time).
En java.time, un momento se representa de tres maneras. Todos tienen una resolución de nanosegundos.
-
Instant
Siempre en UTC. Técnicamente, una cuenta de nanosegundos desde la referencia de época del primer momento de 1970 (1970-01-01T00:00:00Z). -
OffsetDateTime
Una fecha con la hora del día en el contexto de un cierto número de horas-minutos-segundos por delante o por detrás de UTC. -
ZonedDateTime
Una fecha con la hora del día en el contexto de una determinada zona horaria.
Entonces, ¿cuál es la diferencia entre una zona horaria y un offset-from-UTC? Por qué necesitamos clases separadas? Un offset-from-UTC es simplemente un número de horas-minutos-segundos, tres números, ni más ni menos. Un huso horario es mucho más. Un huso horario es una historia de los cambios pasados, presentes y futuros del desfase utilizado por los habitantes de una determinada región.
¿Qué cambios? Cambios dictados por los caprichos o la sabiduría de sus políticos. Los políticos de todo el mundo han mostrado su predilección por cambiar el desfase utilizado por la zona o zonas horarias de su jurisdicción. El horario de verano (DST) es un patrón común de cambios, con su horario a menudo cambiado y la decisión de promulgar o revertir el DST a veces cambiada. También se producen otros cambios, como por ejemplo, en los últimos años, Corea del Norte ha cambiado su reloj en media hora para sincronizarlo con Corea del Sur, Venezuela ha retrasado su reloj media hora para volver a adelantarlo menos de una década después, Turquía ha cancelado este año el cambio programado del horario de verano a la hora estándar sin apenas avisar, y la Rusia contemporánea ha realizado múltiples cambios de este tipo en los últimos años.
Volviendo a tu ejemplo en tu punto # 3, veamos un poco de código.
Digamos que tengo la hora UTC como «02-01-2018 00:03» ¿significa eso que mi hora local de EEUU es «01-01-2018 18:00»?
Tus cadenas de ejemplo tienen otro problema. Ese 03
minuto en la primera parte se ignora su segunda parte, una aparente errata. Lo sé porque no hay ningún ajuste de zona horaria en vigor en América en esa fecha que implique una hora fraccionada de 57 minutos.
Ni un momento
Primero, analizamos su cadena de entrada. Al carecer de cualquier indicador de zona o desplazamiento, debemos parsear utilizando el LocalDateTime
. El nombre LocalDateTime
puede ser engañoso, ya que no significa una localidad específica. Significa cualquiera o todas las localidades. Para más explicación, vea ¿Cuál es la diferencia entre Instant y LocalDateTime?
String input = "2018-01-02T00:03" ; // Text of a date with time-of-day but without any context of time zore or offset-from-UTC. *Not* a moment, *not* a point on the timeline.LocalDateTime ldt = LocalDateTime.parse( input ) ; // Parsing the input as a `LocalDateTime`, a class representing a date with time but no zone/offset. Again, this does *not* represent a moment, is *not* a point on the timeline.
UTC
Por los hechos dados en la Pregunta, sabemos que esta fecha y hora pretendía representar un momento en UTC. Así que podemos asignar el contexto de un offset-from-UTC de cero horas-minutos-segundos para el propio UTC. Aplicamos una ZoneOffset
constante UTC
para obtener un objeto OffsetDateTime
.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ); // We are certain this text was intended to represent a moment in UTC. So correct the faulty text input by assigning the context of an offset of zero, for UTC itself.
Zona horaria
La Pregunta pide ver este momento a través de un reloj de pared con seis horas de retraso respecto al UTC utilizado en Estados Unidos. Una zona horaria con dicho desfase es America/Chicago
.
Especifica un nombre de zona horaria adecuado con el formato de continent/region
, como America/Montreal
Africa/Casablanca
, o Pacific/Auckland
. Nunca utilices la abreviatura de 2 a 4 letras como CST
EST
, o IST
ya que no son verdaderas zonas horarias, no están estandarizadas, y ni siquiera son únicas(!).
ZoneId z = ZoneId.of( "America/Chicago" ) ; // Adjust from UTC to a time zone where the wall-clock time is six hours behind UTC.ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Vea este código ejecutado en vivo en IdeOne.com.
odt.toString(): 2018-01-02T00:03Z
zdt.toString(): 2018-01-01T18:03-06:00
Mismo momento, diferente hora del reloj de pared
Este odt
y zdt
representan el mismo momento simultáneo, el mismo punto en la línea de tiempo. La única diferencia es la hora del reloj de pared.
Trabajemos con un ejemplo, usando Islandia donde su zona horaria usa un offset-from-UTC de cero horas-minutos-segundos. Así que la zona Atlantic/Reykjavik
tiene un tiempo de reloj de pared idéntico al UTC. Al menos actualmente su hora de reloj de pared coincide con UTC; en el pasado o en el futuro puede ser diferente, por lo que es incorrecto decir «UTC es la zona horaria de Islandia». En cualquier caso, nuestro ejemplo… digamos que alguien en Reikiavik, Islandia, con 3 minutos después de la medianoche en el reloj que cuelga de su pared, hace una llamada telefónica a alguien en Estados Unidos. Esa persona de EE.UU. vive en un lugar que utiliza la zona horaria de la región de Chicago. Cuando la persona a la que se llama coge el teléfono, mira el reloj que cuelga de su pared y ve que la hora es justo después de las 6 de la tarde (18:03). Mismo momento, diferente hora del reloj de pared.
También los calendarios que cuelgan de sus paredes son diferentes, ya que es «mañana» en Islandia pero «ayer» en Estados Unidos. Mismo momento, diferentes fechas!
Acerca de java.time
El framework java.time está incorporado en Java 8 y posteriores. Estas clases suplantan a las molestas y antiguas clases de fecha-hora heredadas como java.util.Date
Calendar
&SimpleDateFormat
.
El proyecto Joda-Time, ahora en modo de mantenimiento, aconseja la migración a las clases java.time.
Para saber más, consulte el tutorial de Oracle. Y busca en Stack Overflow muchos ejemplos y explicaciones. La especificación es JSR 310.
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC que cumpla con JDBC 4.2 o posterior. No se necesitan cadenas, ni clases java.sql.*
.
¿Dónde obtener las clases java.time?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, y posteriores – Parte de la API estándar de Java con una implementación incluida.
- Java 9 añade algunas características menores y correcciones.
- Java SE 6 y Java SE 7
- La mayor parte de la funcionalidad de java.time se ha retroportado a Java 6 & 7 en ThreeTen-Backport.
- Android
- Las versiones posteriores de Android agrupan implementaciones de las clases java.time classes.
- Para Android anteriores (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Ver Cómo usar ThreeTenABP….
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puedes encontrar algunas clases útiles aquí como Interval
YearWeek
YearQuarter
, y más.