2011-09-30 13 views
21

Mysql uruchomić na GMT + 8, ale tomcat uruchomić w GMT. przy zapisie datetime do bazy danych, wydają się działać w porządku, kiedy sprawdzić wartość datetime w DB, widzę wartość GMT. Ale kiedy próbuję uzyskać wartość z DB, wartość jest zmieniana, wydaje się, że wartość w DB jest przyjmowana jako GMT + 8, więc java zmień wartość na GMT.Jak zmienić mysql timezone w java połączenie

próbuję ustawić adres URL połączenia dodać

useTimezone=true&serverTimezone=GMT 

ale nie działa

+0

Czy otrzymujesz tylko "niewłaściwą" strefę czasową, czy też sama wartość jest zła? – Thilo

+0

Zmieniam konfigurację, aby użyćGmtMillisForDatetimes = true & serverTimezone = GMT. Wygląda na to, że chcę tego zachowania. ale nadal mylić. – Xilang

Odpowiedz

47

useTimezone jest starszy obejście. Zespół MySQL przepisał całkiem niedawno kod setTimestamp/getTimestamp, ale będzie on włączony tylko wtedy, gdy ustawisz parametr connection useLegacyDatetimeCode = false i używasz najnowszej wersji konektora JDBC mysql. Tak więc na przykład:

String url = 
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false 

Jeśli pobrać kod źródłowy mysql-złącza i spojrzeć na setTimestamp, to bardzo łatwo zobaczyć, co się dzieje:

Jeśli użycie legacy data kod czasowy = false, newSetTimestampInternal (.. .) jest nazywany. Potem, gdy kalendarz przekazane newSetTimestampInternal jest NULL, data obiekt został sformatowany w strefie czasowej bazie danych jest:

this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); 
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ()); 
timestampString = this.tsdf.format(x); 

To bardzo ważne, że kalendarz jest null - więc upewnij się, że używasz:

setTimestamp(int,Timestamp). 

... NIE setTimestamp (int, datownik, kalendarz).

Teraz powinno być oczywiste, jak to działa. Jeśli stworzysz datę: 5 stycznia 2011 r. 3:00 w Ameryce/Los_Angeles (lub dowolnej innej strefie czasowej) przy użyciu java.util.Calendar i wywołaj setTimestamp (1, myDate), to zajmie to twoją datę, użyj SimpleDateFormat sformatować go w strefie czasowej bazy danych . Jeśli więc twój DB jest w Ameryce/New York, to skonstruuje ciąg "2011-01-05 6:00:00" do wstawienia (ponieważ NY wyprzedza LA o 3 godziny).

Aby pobrać datę, użyj getTimestamp (int) (bez kalendarza). Ponownie użyje strefy czasowej bazy danych do zbudowania daty.

Uwaga: Strefa czasowa serwera WWW jest teraz całkowicie nieistotna! Jeśli nie ustawisz useLegacyDatetimecode na wartość false, strefa czasowa serwera WWW jest używana do formatowania - co powoduje wiele zamieszania.


Uwaga:

Możliwe MySQL moich skarżą się, że strefa czasowa serwera jest niejednoznaczna. Na przykład, jeśli baza danych jest skonfigurowany do korzystania EST, nie może być kilka możliwych stref czasowych EST w Javie, więc można to wyjaśnić na mysql-connector mówiąc to właśnie strefa czasowa baza danych jest:

String url = 
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York"; 

Trzeba to zrobić tylko, jeśli narzeka.

+0

Dziękujemy za sugestię useLegacyDatetimeCode!Uwaga: To również rozwiązało moje problemy z pracą z czasem Jody (za pośrednictwem dodatku hibernacji usertypes). – Pete

+0

Tak więc z serverTimezone i useLegacyDatetimeCode dodane do mojego ciąg połączenia, mogę wysłać Timestmp i zostanie poprawnie zarejestrowane w kolumnie DateTime, ponieważ jest to czas UTC. Widzę to na mojej konsoli MySQL jako takiej. Kiedy wykonuję SELECT przez JDBC i próbuję uzyskać dane, to nadal automatycznie konwertuje je w warstwie JDBC. Próbowałem getObject() i geTimestmp (zarówno bez obiektu z obiektem kalendarza UTC, jak i z niego) i ciągle wraca w czasie lokalnym. – djsumdog

+0

Okazuje się, że było to ustawienie potrzebne do rozwiązania problemu produkcyjnego. Lokalnie nie mogliśmy tego odtworzyć. Ale próbując tego w kierowcy przy produkcji wyeliminowano stoisko, które widzimy po 10-30 sekundach przetwarzania. –