Mysql
 sql >> Database >  >> RDS >> Mysql

Discrepanza TimeZone in MySQL e Java

Sfondo:un'idea sbagliata sorprendentemente comune e diffusa condivisa anche da programmatori brillanti è l'idea che i timestamp memorizzati (nel database, nella data, nel calendario, nel timestamp e altri) abbiano in qualche modo informazioni sul fuso orario. Non lo fanno. Un timestamp (fino a Java 8, comunque) viene memorizzato come numero di millisecondi dalla mezzanotte del 1 gennaio 1970 UTC. Fine della frase. L'unica cosa che fa l'impostazione del fuso orario è fornire informazioni sufficienti al computer per convertire quel timestamp in un formato leggibile dall'uomo e viceversa.

Risposta:Quando hai sospettato che si trattasse di un problema di fuso orario, avevi ragione . Ma anche il codice che hai usato per provare a verificarlo ha un problema:

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

Quel setTimeZone l'affermazione non ha nessun effetto sull'ora memorizzata in end , perché l'ora è già stata impostata. Avrebbe avuto effetto solo se avessi memorizzato l'ora in seguito, e quindi solo se avessi usato uno dei metodi di Calendar che ha convertito l'ora da un formato leggibile dall'uomo (e non setTimeInMillis ).

Quando usi getTimeInMillis per trasmettere il timestamp all'estratto conto preparato, stai recuperando direttamente il timestamp. Dal momento che non lo stai convertendo in un formato umano, ancora una volta le informazioni sul fuso orario vengono ignorate.

Quando ci provi

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

e

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

le cose appaiono per funzionare perché ora stai usando metodi che convertono in/da un formato leggibile dall'uomo e quindi vengono utilizzate le informazioni sul fuso orario specificate. Tuttavia, questo sta solo coprendo il vero problema. Il vero problema è che l'ora è stata convertita in modo errato quando l'hai analizzata da endString . Cioè, il fuso orario che endString è stato espresso in non corrisponde al fuso orario impostato in df1 al momento dell'analisi della data.

RISPOSTA BREVE:prima di questa riga:

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

Devi:

  • Scopri quale fuso orario è l'ora in endString era espresso in.
  • Imposta df1 e non end a quello stesso fuso orario. Da df1 è la cosa che converte la data dal formato umano, sono le informazioni sul fuso orario che vengono utilizzate.

Saluti!