¿Cómo configurar la zona horaria de java.util.Date?
He analizado a java.util.Date
desde a String
pero está configurando la zona horaria local como la zona horaria del date
objeto.
La zona horaria no se especifica en el String
origen desde el que Date
se analiza. Quiero establecer una zona horaria específica del date
objeto.
¿Cómo puedo hacer eso?
Utilice formato de fecha. Por ejemplo,
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
Tenga en cuenta que java.util.Date
los objetos no contienen información de zona horaria por sí mismos; no puede establecer la zona horaria en un Date
objeto. Lo único que Date
contiene un objeto es una cantidad de milisegundos desde la "época": el 1 de enero de 1970, 00:00:00 UTC.
Como muestra ZZ Coder, usted configura la zona horaria en el DateFormat
objeto para indicarle en qué zona horaria desea mostrar la fecha y la hora.
tl; dr
…analizado… desde una cadena… la zona horaria no está especificada… Quiero establecer una zona horaria específica
LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
No hay zona horaria en juDate
Como indicaron las otras respuestas correctas, java.util.Date no tiene zona horaria † . Representa UTC /GMT (sin desplazamiento de zona horaria). Muy confuso porque su toString
método aplica la zona horaria predeterminada de la JVM al generar una representación de cadena.
Evite la cita judaica
Por esta y muchas otras razones, debe evitar el uso de java.util.Date & .Calendar & java.text.SimpleDateFormat integrados. Son notoriamente problemáticos.
En su lugar, utilice el paquete java.time incluido con Java 8 .
java.tiempo
Las clases java.time pueden representar un momento en la línea de tiempo de tres maneras:
- UTC (
Instant
) - Con un desplazamiento (
OffsetDateTime
conZoneOffset
) - Con zona horaria (
ZonedDateTime
conZoneId
)
Instant
En java.time , el componente básico es Instant
un momento en la línea de tiempo en UTC. Utilice Instant
objetos para gran parte de su lógica empresarial.
Instant instant = Instant.now();
OffsetDateTime
Aplique un desplazamiento desde UTC para ajustarse a la hora del reloj de pared de alguna localidad .
Aplique a ZoneOffset
para obtener un OffsetDateTime
.
ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
ZonedDateTime
Mejor es aplicar una zona horaria , un desplazamiento más las reglas para manejar anomalías como el horario de verano (DST) .
Aplique a ZoneId
a an Instant
para obtener un ZonedDateTime
. Especifique siempre un nombre de zona horaria adecuado . Nunca utilice 3 o 4 abreviaturas como EST
o IST
que no sean únicas ni estandarizadas.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDateTime
Si la cadena de entrada carecía de algún indicador de desplazamiento o zona, analícela como un archivo LocalDateTime
.
Si está seguro de la zona horaria deseada, asigne un ZoneId
para producir un archivo ZonedDateTime
. Vea el ejemplo de código anterior en la sección tl;dr en la parte superior.
Cadenas formateadas
Llame al toString
método en cualquiera de estas tres clases para generar una cadena que represente el valor de fecha y hora en el formato estándar ISO 8601 . La ZonedDateTime
clase amplía el formato estándar añadiendo el nombre de la zona horaria entre paréntesis.
String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
Para otros formatos utilice la DateTimeFormatter
clase. Generalmente es mejor dejar que esa clase genere formatos localizados utilizando el lenguaje humano y las normas culturales esperados del usuario. O puede especificar un formato particular.
Acerca de java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases reemplazan a las antiguas y problemáticas clases de fecha y hora heredadas , como java.util.Date
, Calendar
y SimpleDateFormat
.
Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*
clases. Hibernate 5 y JPA 2.2 admiten java.time .
¿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 de Java estándar con una implementación incluida.
- Java 9 trajo algunas características y correcciones menores.
- Java SE 6 y Java SE 7
- La mayor parte de la funcionalidad java.time está adaptada a Java 6 y 7 en ThreeTen-Backport .
- Androide
- Versiones posteriores de implementaciones de paquetes de Android (26+) de las clases java.time .
- Para Android anterior (<26), un proceso conocido como eliminación de azúcar de API aporta un subconjunto de la funcionalidad java.time que no estaba integrada originalmente en Android.
- Si el desazucar no ofrece lo que necesitas, el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) a Android. Consulte Cómo utilizar ThreeTenABP… .
Tiempo Joda
Si bien Joda-Time todavía se mantiene activamente, sus creadores nos han dicho que migremos a java.time tan pronto como sea conveniente. Dejo esta sección intacta como referencia, pero sugiero usar la java.time
sección anterior en su lugar.
En Joda-Time , un objeto de fecha y hora ( DateTime
) realmente conoce su zona horaria asignada. Eso significa una desviación de UTC y las reglas y el historial del horario de verano (DST) de esa zona horaria y otras anomalías similares.
String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
Llame al toString
método para generar una cadena en formato ISO 8601 .
String output = dateTimeIndia.toString();
Joda-Time también ofrece amplias capacidades para generar todo tipo de formatos de cadenas.
Si es necesario, puede convertir de Joda-Time DateTime a java.util.Date.
Java.util.Date date = dateTimeIndia.toDate();
Busque en StackOverflow "joda date" para encontrar muchos más ejemplos, algunos bastante detallados.
† En realidad , hay una zona horaria integrada en java.util.Date, que se utiliza para algunas funciones internas (consulte los comentarios en esta respuesta). Pero esta zona horaria interna no está expuesta como una propiedad y no se puede configurar. Esta zona horaria interna no es la que utiliza el toString
método para generar una representación de cadena del valor de fecha y hora; en su lugar, la zona horaria predeterminada actual de la JVM se aplica sobre la marcha. Entonces, como abreviatura, solemos decir "juDate no tiene zona horaria". ¿Confuso? Sí. Otra razón más para evitar estas viejas y cansadas clases.
También puedes configurar la zona horaria a nivel de JVM.
Date date1 = new Date();
System.out.println(date1);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// or pass in a command line arg: -Duser.timezone="UTC"
Date date2 = new Date();
System.out.println(date2);
producción:
Thu Sep 05 10:11:12 EDT 2013
Thu Sep 05 14:11:12 UTC 2013