Tengo zona horaria problema relacionado.
Tengo un programa de base de datos Java y MySQL. No utilizar cualquier ORM, pero tengo biblioteca personalizada que utiliza JDBC conector mysql java v 6.0.4
Puedo enviar ajustes como parte de la cadena como:
serverTimezone - America/Chicago
useTimezone - true
useJDBCCompliantTimezoneShift - false
useLegacyDatetimeCode - false
Trato de elegir una fecha en db por ejemplo 2019-02-13
.
La base de datos se encuentra en la zona horaria de EE.UU. / Oriental y programa de servidor Java corriendo se encuentra en la zona horaria America / Chicago.
No hay manera de cambiar la zona de ubicación / hora de cualquiera de los servidores.
En Java, aparece un día uno hacia atrás día ( 2019-02-12
). El problema es causado debido a la marca de tiempo -
1550034000
es 2019-02-13 00:00:00
en los Estados Unidos / Oriente
pero
1550034000
es 2019-02-12 23:00:00
en América / Chicago
Así como el resultado tengo java.sql.Date
objeto con fecha 2019-02-12
. No hay ayuda para agregar zona horaria compensado porque la información de tiempo está separada de la fecha.
Se puede proponer alguna solución sobre cómo obtener una fecha adecuada y sin cambio de zona horaria?
Editar: Estoy utilizando serverTimezone
entorno pero no estoy seguro de si el valor debe ser zona horaria de base de datos que está utilizando o que simplemente está anulando zona horaria de JVM / servidor que ejecuta la aplicación.
En primer lugar, he leído que no se puede, en su caso, pero para otros lectores quisiera estado que la recomendación general es ejecutar todo en UTC, al menos cuando abarca más de una zona horaria. Así que esta habría sido la mejor solución a su problema.
En segundo lugar, ya que ambos I y Gord Thompson he mencionado en los comentarios, la segunda mejor solución es manejar fechas tan LocalDate
, no java.sql.Date
. Mientras que el segundo sólo finge que no tienen hora del día, lo que realmente tiene problemas de diseño que hacen que sea difícil de resolver su problema. Una LocalDate
realidad es una fecha sin hora del día y sin zona horaria, por lo que debería ser una apuesta que es mucho más seguro (salvo que los controladores de base de datos que convierten incorrectamente hacia y desde LocalDate
han oído hablar de; Mantengo mis dedos cruzados, de nuevo correr todo en UTC eliminaría esos errores también). Editar: Suponiendo que usted puede modificar su biblioteca JDBC costumbre, aquí es cómo conseguir una LocalDate
de un ResultSet
:
LocalDate correctDateDirectlyFromDatabase
= yourResultSet.getObject("yourDateColumn", LocalDate.class);
Se requiere por lo menos de JDBC 4.2, es probable que tenga que.
Si ninguno de los anteriores está disponible para usted, aquí viene la manera de reparar la incorrecta Date
que obtuvo de la base de datos. Es un poco de un truco, pero funcionará.
import java.sql.Date;
// …
// Modern ID of the time zone previously known as US/Eastern
ZoneId datebaseTimeZone = ZoneId.of("America/New_York");
Date dateFromDatabase = new Date(TimeUnit.SECONDS.toMillis(1_550_034_000));
System.out.println("Date as retrieved from database (or pretending): " + dateFromDatabase);
long epochMillis = dateFromDatabase.getTime();
ZonedDateTime dateTime = Instant.ofEpochMilli(epochMillis)
.atZone(datebaseTimeZone);
LocalDate realDate = dateTime.toLocalDate();
// Sanity check
if (! realDate.atStartOfDay(datebaseTimeZone).equals(dateTime)) {
throw new IllegalStateException("Failed to convert date correctly from " + datebaseTimeZone + " time zone");
}
System.out.println("Date is " + realDate);
Cuando me encontré con esto en la zona horaria America / Chicago, se imprime:
Date as retrieved from database (or pretending): 2019-02-12 Date is 2019-02-13
He intentado funcionar en otras zonas horarias. En algunas zonas de tiempo de imprimir la primera línea 2019-02-12
, en otros 2019-02-13
. La última línea se imprime 2019-02-13
en todas las zonas horarias que he probado.
Ahora te he dado una LocalDate
. Eso es bueno, esto es lo que debe querer utilizar en su procesamiento posterior. En caso de que necesite una java.sql.Date
a otra API legado que no desea cambiar por el momento, volver a convertir una correcta java.sql.Date
esta manera:
Date oldfashionedJavaSqlDate = Date.valueOf(realDate);
System.out.println("Date converted back to " + oldfashionedJavaSqlDate);
Fecha convierte de nuevo en 02/13/2019
Y cuando digo correcto, se requiere que nadie está manipulando la zona horaria predeterminada de la JVM, que es fácil para cualquier programa que se ejecuta en la JVM hacer.
Enlace: Oracle tutorial: Fecha Hora que explica cómo utilizar java.time.