Antecedentes:un concepto erróneo sorprendentemente común y grande compartido incluso por programadores brillantes es la noción de que las marcas de tiempo almacenadas (en su base de datos, fecha, calendario, marca de tiempo, etc.) de alguna manera tienen información de zona horaria. No lo hacen. Una marca de tiempo (hasta Java 8, de todos modos) se almacena como el número de milisegundos desde la medianoche del 1 de enero de 1970 UTC. Fin de frase. Lo único que hace la configuración de la zona horaria es proporcionar suficiente información a la computadora para convertir esa marca de tiempo a un formato legible por humanos, y viceversa.
Respuesta:Cuando sospechaste que se trataba de un problema de zona horaria, tenías razón . Pero el código que usó para intentar verificar esto también tiene un problema:
end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));
Ese setTimeZone
declaración tiene ningún efecto en el tiempo almacenado en end
, porque ya se ha fijado la hora. Solo habría tenido un efecto si almacenaste la hora después, y solo si usaste uno de los métodos de Calendar que convirtió la hora de un formato legible por humanos (y no setTimeInMillis
).
Cuando usas getTimeInMillis
para pasar la marca de tiempo a su estado de cuenta preparado, está recuperando la marca de tiempo directamente. Como no lo está convirtiendo a un formato humano, una vez más se ignora la información de la zona horaria.
Cuando intentas
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
end.setTime(sdf.parse("2012-10-01 00:00:00"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));
y
pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));
las cosas aparecen funcione porque ahora está usando métodos que convierten a/desde un formato legible por humanos y, por lo tanto, se usa la información de zona horaria especificada. Sin embargo, esto solo está encubriendo el verdadero problema. El verdadero problema es que la hora se convirtió incorrectamente cuando la analizó desde endString
. Es decir, la zona horaria que endString
se expresó en no coincide con la zona horaria establecida en df1
en el momento en que se analizó la fecha.
RESPUESTA CORTA:antes de esta línea:
end.setTime(df1.parse(endString));
Necesitas:
- Averigüe en qué zona horaria la hora en
endString
se expresó en. - Establecer
df1
y noend
a esa misma zona horaria. Desdedf1
es lo que está convirtiendo la fecha del formato humano, es esa información de zona horaria la que se usa.
¡Salud!