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

TimeZone uoverensstemmelse i mysql og java

Baggrund:En overraskende almindelig – og stor – misforståelse, som deles af selv geniale programmører, er forestillingen om, at gemte tidsstempler (i din database, Dato, Kalender, Tidsstempel, et al.) på en eller anden måde har tidszoneoplysninger. Det gør de ikke. Et tidsstempel (i hvert fald indtil Java 8) gemmes som antallet af millisekunder siden midnat den 1. januar 1970 UTC. Slut på sætning. Det eneste, som indstiller tidszonen, er at give computeren nok information til at konvertere tidsstemplet til et format, der kan læses af mennesker, og omvendt.

Svar:Da du havde mistanke om, at dette var et tidszoneproblem, har du ret . Men koden du brugte til at prøve at bekræfte dette har også et problem:

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

Det setTimeZone erklæring har ingen effekt på det tidspunkt, der er gemt i end , fordi tiden allerede er indstillet. Det ville kun have haft en effekt, hvis du gemte tiden bagefter, og så kun hvis du brugte en af ​​Kalenders metoder, som konverterede tiden fra et menneskeligt læsbart format (og ikke setTimeInMillis ).

Når du bruger getTimeInMillis for at videregive tidsstemplet til din udarbejdede erklæring, henter du tidsstemplet direkte. Da du ikke konverterer det til et menneskeligt format, ignoreres tidszoneinformationen igen.

Når du prøver

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

og

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

ting vises til at virke, fordi du nu bruger metoder, der konverterer til/fra et menneskeligt læsbart format, og derfor bruges den angivne tidszoneinformation. Dette dækker dog kun over det egentlige problem. Det virkelige problem er, at klokkeslættet blev konverteret forkert, da du analyserede det fra endString . Det vil sige den tidszone, som endString blev udtrykt i, stemmer ikke overens med tidszonen indstillet i df1 på det tidspunkt, hvor datoen blev parset.

KORT SVAR:før denne linje:

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

Du skal:

  • Find ud af, hvilken tidszone tiden er i endString kom til udtryk i.
  • Indstil df1 og ikke end til samme tidszone. Siden df1 er det, der konverterer datoen fra et menneskeligt format, det er den tidszoneinformation, der bruges.

Skål!



  1. C# svarende til SQL Server DataTypes

  2. Sådan installeres og konfigureres MySQL på Ubuntu

  3. Hvorfor (og hvordan) opdele kolonne ved hjælp af master..spt_values?

  4. MariaDB JSON_ARRAY_INSERT() Forklaret