Esta es la solución más exacta que encomtrarás dar, sin embargo obsérvala detenidamente y analiza si se puede adaptar a tu trabajo.
Solución:
Lo siento mucho, pero todas las respuestas hasta ahora son generalmente incorrectas. La respuesta es bastante sencilla pero requiere que separemos cinco puntos:
- DATE = java.sql.Date, que es un contenedor alrededor de java.util.Date que es la cantidad de milisegundos desde la Época en la zona horaria UTC. Esto tiene el año/mes/fecha/horas/minutos/segundos en una zona horaria fija GMT+0 (UTC). Sin embargo, tenga en cuenta que java.sql.Date establece los componentes de tiempo en cero.
- TIMESTAMP = java.sql.TimeStamp, que es un contenedor de componentes alrededor de la fecha que agrega fracciones de segundo para admitir el estándar de tipo SQL DATE. Esta clase/tipo no es relevante ni necesaria para esta pregunta, pero en resumen, tiene la fecha más la hora.
- La base de datos almacena objetos DATE como se define (usando UTC como el desplazamiento de Java) pero mayo traduce la hora si está configurada en la base de datos para estar en una zona horaria diferente. De forma predeterminada, la mayoría de las bases de datos utilizan la zona horaria del servidor local, lo cual es una muy mala idea. Señoras, señores… Almacenar SIEMPRE los objetos DATE en UTC. sigue leyendo…
- La hora en la JVM y la zona horaria debe ser correcta. Dado que el objeto Date está utilizando UTC, ¿se calcula un desplazamiento para la hora de su servidor? Considere eso con la fuerte recomendación de que la hora del servidor se establezca en GMT+0 (UTC).
- Finalmente, cuando queremos representar la FECHA de la base de datos (usando JSF o lo que sea), deberían estar configurado para ser la zona horaria GMT + 0 y, si se hace desde el servidor también … sus fechas y horas SIEMPRE serán consistentes, referenciales y todas las cosas buenas. Todo lo que queda es representar la hora y ESTO es donde el agente de usuario (para una aplicación web, por ejemplo) pudo utilizarse para traducir la hora GMT+0 a la zona horaria “local” de los usuarios.
Resumen: Use UTC (GMT+0) en el servidor, en la base de datos, en sus objetos Java.
DATE y TIMESTAMP solo son diferentes desde la perspectiva de la base de datos en que TIMESTAMP lleva fracciones de segundos adicionales. Ambos usan GMT+0 (implícito). JodaTime es un marco de calendario preferido para lidiar con todo esto, pero no solucionará los problemas de JVM no coincidentes con la configuración de la zona horaria de la base de datos.
Si los diseños de aplicaciones de JVM a DB no usan GMT, debido al horario de verano, los ajustes de reloj y todo tipo de otros juegos regionales que se juegan en los relojes locales del mundo… los tiempos de las transacciones y todo lo demás estarán sesgados para siempre. , no referencial, inconsistente, etc.
Otra buena respuesta relacionada con los tipos de datos: java.util.Date vs java.sql.Date
También tenga en cuenta que Java 8 tiene actualizaciones con un mejor manejo de fecha/hora (finalmente), pero esto no soluciona el hecho de que el reloj del servidor en el que se ejecuta la JVM esté en una zona horaria y la base de datos esté en otra. En este punto siempre está ocurriendo la traducción. En cada cliente grande (inteligente) con el que trabajo, las zonas horarias de la base de datos y del servidor JVM están configuradas en UTC por este mismo motivo, incluso si sus operaciones ocurren en gran medida en alguna otra zona horaria.
Después de mucho experimentar y buscar, estoy bastante seguro de haber encontrado la causa del problema. La fecha se mantiene en un java.util.Date que viene con todo el equipaje de tiempo y una zona horaria. Parecería que JPA está leyendo la fecha 18 de septiembre de 2003 de la base de datos y luego completando la fecha de esta manera: “Jue 18 de septiembre 00:00:00 BST 2003” – observe que la zona horaria se ha configurado en BST probablemente porque no lo estaba establecido explícitamente por la base de datos. De todos modos, es necesario formatear la salida en la página JSF si solo desea ver la fecha de esta manera:
Esto, sin embargo, asume que la zona horaria es la que está vigente actualmente en la máquina. En mi caso, la zona horaria actualmente es GMT (porque es invierno), por lo que cuando se le presenta la fecha “Jue 18 de septiembre a las 00:00:00 BST 2003”, la convierte a GMT restando una hora y la pantalla muestra el 17 de septiembre de 2003.
Yo tuve el mismo problema. No sé la razón, pero mi solución fue la siguiente:
En la base de datos cambié el tipo de columna de DATE
para DATETIME
.
En la clase de entidad cambié el @Temporal
anotación pero mantuvo el tipo de datos Date
:
@Temporal(TemporalType.TIMESTAMP)
private Date myDate;
Si piensas que te ha resultado provechoso nuestro post, nos gustaría que lo compartas con el resto juniors de esta forma nos ayudas a dar difusión a esta información.