sql >> Databáze >  >> RDS >> Mysql

Nesrovnalosti v časovém pásmu v mysql a java

Pozadí:Překvapivě běžnou – a velkou – mylnou představou, kterou sdílejí i brilantní programátoři, je představa, že uložená časová razítka (ve vaší databázi, Datum, Kalendář, Časové razítko atd.) nějakým způsobem obsahují informace o časovém pásmu. Nedělají. Časová známka (až do Java 8) je uložena jako počet milisekund od půlnoci 1. ledna 1970 UTC. Konec věty. Jediná věc, kterou nastavení časového pásma dělá, je poskytnout počítači dostatek informací k převedení časového razítka do formátu čitelného člověkem a naopak.

Odpověď:Když jste měli podezření, že se jedná o problém s časovým pásmem, měli jste pravdu . Ale kód, který jste použili k ověření, má také problém:

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

To setTimeZone prohlášení nemá žádný účinek v čase uloženém v end , protože čas již byl nastaven. Účinek by to mělo pouze tehdy, pokud byste čas uložili později, a to pouze tehdy, pokud byste použili jednu z metod Kalendáře, která převedla čas z formátu čitelného člověkem (a nikoli setTimeInMillis ).

Když použijete getTimeInMillis pro předání časového razítka do připraveného výpisu získáváte časové razítko přímo. Protože jej nepřevádíte do lidského formátu, informace o časovém pásmu jsou opět ignorovány.

Když to zkusíte

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

a

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

věci se objevují fungovat, protože nyní používáte metody, které převádějí do/z formátu čitelného člověkem, a proto se používají zadané informace o časovém pásmu. To však pouze zakrývá skutečný problém. Skutečným problémem je, že čas byl nesprávně převeden, když jste jej analyzovali z endString . Tedy časové pásmo, které endString byl vyjádřen v neodpovídá časovému pásmu nastavenému v df1 v době, kdy bylo datum analyzováno.

KRÁTKÁ ODPOVĚĎ:před tímto řádkem:

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

Musíte:

  • Zjistěte, v jakém časovém pásmu je čas v endString byl vyjádřen v.
  • Nastavte df1 a ne end do stejného časového pásma. Od df1 je věc, která převádí datum z lidského formátu, jsou to informace o časovém pásmu, které se používají.

Na zdraví!



  1. Smazat všechny cizí klíče v databázi (MySql)

  2. Může MySQL Nested Select vrátit seznam výsledků

  3. Uložené procedury jsou ve světě php/mysql no-go?

  4. Jak spravovat své databáze PostgreSQL z rozhraní CLI ClusterControl