sql >> Databasteknik >  >> RDS >> Mysql

TimeZone-avvikelse i mysql och java

Bakgrund:En förvånansvärt vanlig – och stor – missuppfattning som delas av även briljanta programmerare är uppfattningen att lagrade tidsstämplar (i din databas, Datum, Kalender, Tidstämpel, et al) på något sätt har tidszoninformation. Det gör de inte. En tidsstämpel (fram till Java 8 i alla fall) lagras som antalet millisekunder sedan midnatt den 1 januari 1970 UTC. Slutet på meningen. Det enda som ställer in tidszonen är att tillhandahålla tillräckligt med information till datorn för att konvertera den tidsstämpeln till ett läsbart format, och vice versa.

Svar:När du misstänkte att detta var ett tidszonproblem, har du rätt . Men koden du använde för att verifiera detta har också ett problem:

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

Den där setTimeZone uttalandet har ingen effekt på tiden som är lagrad i end , eftersom tiden redan är inställd. Det hade bara haft effekt om du lagrade tiden efteråt, och då bara om du använde någon av Kalenders metoder som konverterade tiden från ett mänskligt läsbart format (och inte setTimeInMillis ).

När du använder getTimeInMillis för att skicka tidsstämpeln till ditt förberedda utdrag, hämtar du tidsstämpeln direkt. Eftersom du inte konverterar det till ett mänskligt format, ignoreras återigen tidszonsinformationen.

När du försöker

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

och

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

saker visas att fungera eftersom du nu använder metoder som konverterar till/från ett mänskligt läsbart format, och därför används den angivna tidszonsinformationen. Detta döljer dock bara det verkliga problemet. Det verkliga problemet är att tiden konverterades felaktigt när du analyserade den från endString . Det vill säga tidszonen som endString uttrycktes i stämmer inte överens med tidszonen i df1 vid den tidpunkt då datumet analyserades.

KORT SVAR:före denna rad:

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

Du måste:

  • Ta reda på vilken tidszon tiden är i endString uttrycktes i.
  • Ställ in df1 och inte end till samma tidszon. Sedan df1 är det som konverterar datumet från mänskligt format, det är den tidszonsinformationen som används.

Skål!



  1. Använder PHPExcel för att skapa automatiskt genererade Excel-filer

  2. How to_timestamp() Fungerar i PostgreSQL

  3. Vad är lösningen för att använda dynamisk SQL i en lagrad procedur

  4. Parametrisera en SQL IN-sats