Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Zeitzonenabweichung in mysql und java

Hintergrund:Ein überraschend häufiges – und großes – Missverständnis, das sogar von brillanten Programmierern geteilt wird, ist die Vorstellung, dass gespeicherte Zeitstempel (in Ihrer Datenbank, Datum, Kalender, Zeitstempel usw.) irgendwie Zeitzoneninformationen enthalten. Sie tun es nicht. Ein Zeitstempel (zumindest bis Java 8) wird als Anzahl der Millisekunden seit Mitternacht am 1. Januar 1970 UTC gespeichert. Ende des Satzes. Das einzige, was das Einstellen der Zeitzone bewirkt, ist, dem Computer genügend Informationen bereitzustellen, um diesen Zeitstempel in ein für Menschen lesbares Format umzuwandeln und umgekehrt.

Antwort:Als Sie vermuteten, dass es sich um ein Zeitzonenproblem handelt, hatten Sie Recht . Aber auch der Code, mit dem Sie versucht haben, dies zu überprüfen, hat ein Problem:

end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

Das setTimeZone Anweisung hat keine Wirkung auf die in end gespeicherte Zeit , weil die Uhrzeit bereits eingestellt ist. Es hätte nur einen Effekt gehabt, wenn Sie die Zeit danach gespeichert hätten, und auch nur dann, wenn Sie eine der Methoden von Calendar verwendet hätten, die die Zeit aus einem für Menschen lesbaren Format konvertiert hätten (und nicht setTimeInMillis ).

Wenn Sie getTimeInMillis verwenden Um den Zeitstempel an Ihre vorbereitete Anweisung zu übergeben, rufen Sie den Zeitstempel direkt ab. Da Sie es nicht in ein menschliches Format konvertieren, werden die Zeitzoneninformationen erneut ignoriert.

Wenn Sie es versuchen

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()));

und

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));

Dinge erscheinen funktionieren, da Sie jetzt Methoden verwenden, die in ein/aus einem für Menschen lesbaren Format konvertieren, und daher die angegebenen Zeitzoneninformationen verwendet werden. Dies verschleiert jedoch nur das eigentliche Problem. Das eigentliche Problem ist, dass die Zeit falsch konvertiert wurde, als Sie sie von endString geparst haben . Das heißt, die Zeitzone, die endString wurde ausgedrückt in stimmt nicht mit der in df1 eingestellten Zeitzone überein zum Zeitpunkt der Analyse des Datums.

KURZE ANTWORT:vor dieser Zeile:

end.setTime(df1.parse(endString));

Sie müssen:

  • Finden Sie heraus, welche Zeitzone die Zeit in endString ist wurde ausgedrückt in.
  • Setze df1 und nicht end in dieselbe Zeitzone. Seit df1 ist das Ding, das das Datum aus dem menschlichen Format konvertiert, es sind diese Zeitzoneninformationen, die verwendet werden.

Prost!