Muszę wymusić wszystkie operacje związane z czasem na GMT / UTC, niezależnie od strefy czasowej ustawionej na komputerze. Jakikolwiek wygodny sposób na to w kodzie?
Aby wyjaśnić, używam czasu serwera DB do wszystkich operacji, ale wychodzi on sformatowany zgodnie z lokalną strefą czasową.
Dzięki!
Odpowiedzi:
OP odpowiedział na to pytanie, aby zmienić domyślną strefę czasową dla pojedynczej instancji działającej maszyny JVM, ustawić
user.timezone
właściwość systemu:java -Duser.timezone=GMT ... <main-class>
Jeśli potrzebujesz ustawić określone strefy czasowe podczas pobierania obiektów Data / Czas / Znacznik czasu z bazy danych
ResultSet
, użyj drugiej formygetXXX
metod, które przyjmująCalendar
obiekt:Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); ResultSet rs = ...; while (rs.next()) { Date dateValue = rs.getDate("DateColumn", tzCal); // Other fields and calculations }
Lub ustawiając datę w PreparedStatement:
Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); PreparedStatement ps = conn.createPreparedStatement("update ..."); ps.setDate("DateColumn", dateValue, tzCal); // Other assignments ps.executeUpdate();
Zapewni to spójność wartości przechowywanej w bazie danych, gdy kolumna bazy danych nie przechowuje informacji o strefie czasowej.
java.util.Date
Ijava.sql.Date
zajęcia zapisać aktualny czas (w milisekundach) UTC. Aby sformatować je na wyjściu w innej strefie czasowej, użyjSimpleDateFormat
. Możesz również powiązać strefę czasową z wartością za pomocą obiektu Calendar:TimeZone tz = TimeZone.getTimeZone("<local-time-zone>"); //... Date dateValue = rs.getDate("DateColumn"); Calendar calValue = Calendar.getInstance(tz); calValue.setTime(dateValue);
Przydatne odniesienie
https://docs.oracle.com/javase/9/troubleshoot/time-zone-settings-jre.htm#JSTGD377
https://confluence.atlassian.com/kb/setting-the-timezone-for-the-java-environment-841187402.html
źródło
Również jeśli możesz ustawić strefę czasową JVM w ten sposób
System.setProperty("user.timezone", "EST");
lub
-Duser.timezone=GMT
w argumentach JVM.źródło
System.setProperty("user.timezone" ...)
nie działa.Musiałem ustawić strefę czasową JVM dla Windows 2003 Server, ponieważ zawsze zwracał GMT dla nowej daty ();
-Duser.timezone=America/Los_Angeles
Lub odpowiednią strefę czasową. Znalezienie listy stref czasowych okazało się również pewnym wyzwaniem ...
Oto dwie listy;
http://wrapper.tanukisoftware.com/doc/english/prop-timezone.html
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzatz%2F51%2Fadmin%2Freftz.htm
źródło
Możesz zmienić strefę czasową za pomocą TimeZone.setDefault () :
TimeZone.setDefault(TimeZone.getTimeZone("GMT"))
źródło
dla mnie tylko szybki SimpleDateFormat,
private static final SimpleDateFormat GMT = new SimpleDateFormat("yyyy-MM-dd"); private static final SimpleDateFormat SYD = new SimpleDateFormat("yyyy-MM-dd"); static { GMT.setTimeZone(TimeZone.getTimeZone("GMT")); SYD.setTimeZone(TimeZone.getTimeZone("Australia/Sydney")); }
następnie sformatuj datę, używając innej strefy czasowej.
źródło
tl; dr
String sql = "SELECT CURRENT_TIMESTAMP ; … OffsetDateTime odt = myResultSet.getObject( 1 , OffsetDateTime.class ) ;
Unikaj zależności od systemu operacyjnego hosta lub maszyny JVM dla domyślnej strefy czasowej
Zalecam napisanie całego kodu w celu jawnego określenia żądanej / oczekiwanej strefy czasowej. Nie musisz polegać na bieżącej domyślnej strefie czasowej maszyny JVM. Należy również pamiętać, że bieżąca domyślna strefa czasowa maszyny JVM może ulec zmianie w dowolnym momencie podczas działania, z dowolnym kodem w dowolnym wątku wywołania dowolnej aplikacji
TimeZone.setDefault
. Takie wywołanie ma natychmiastowy wpływ na wszystkie aplikacje w tej maszynie JVM.java.time
Niektóre z pozostałych odpowiedzi były poprawne, ale obecnie są przestarzałe. Okropne klasy data-czas dołączone do najwcześniejszych wersji Javy były błędne, napisane przez ludzi, którzy nie rozumieli złożoności i subtelności obsługi daty i godziny.
Starsze klasy daty i godziny zostały zastąpione przez klasy java.time zdefiniowane w JSR 310.
Aby przedstawić strefę czasową, użyj
ZoneId
. Aby przedstawić przesunięcie od czasu UTC, użyjZoneOffset
. Przesunięcie to zaledwie kilka godzin-minut-sekund przed lub za głównym południkiem. Strefa czasowa to znacznie więcej. Strefa czasowa to historia przeszłych, obecnych i przyszłych zmian offsetu używanego przez mieszkańców określonego regionu.Aby uzyskać przesunięcie równe zero godzin-minut-sekund, użyj stałej
ZoneOffset.UTC
.Instant
Aby uchwycić aktualny moment w UTC, użyj pliku
Instant
. Ta klasa reprezentuje moment w UTC, z definicji zawsze w UTC.Instant instant = Instant.now() ; // Capture current moment in UTC.
ZonedDateTime
Aby zobaczyć ten sam moment przez zegar ścienny używany przez mieszkańców danego regionu, dostosuj się do strefy czasowej. Ten sam moment, ten sam punkt na osi czasu, inny zegar ścienny.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ; ZonedDateTime zdt = instant.atZone( z ) ;
Baza danych
Wspominasz o bazie danych.
Aby pobrać moment z bazy danych, twoja kolumna powinna być typu danych zbliżonego do standardu SQL
TIMESTAMP WITH TIME ZONE
. Pobierz obiekt, a nie ciąg. W JDBC 4.2 i nowszych możemy wymieniać obiekty java.time z bazą danych.OffsetDateTime
Jest wymagane przez JDBC, podczasInstant
iZonedDateTime
są opcjonalne.Sądzę, że w większości baz danych i sterowników uzyskasz moment taki jak w UTC. Ale jeśli nie, możesz to zmienić na dwa sposoby:
Instant
:odt.toInstant()
Informacje o java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak
java.util.Date
,Calendar
, iSimpleDateFormat
.Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .
Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani
java.sql.*
klas.Skąd wziąć klasy java.time?
źródło
Pobrałbym czas z bazy danych w postaci surowej (długi znacznik czasu lub data java), a następnie użyłbym SimpleDateFormat do sformatowania go lub Kalendarza, aby nim manipulować. W obu przypadkach należy ustawić strefę czasową obiektów przed ich użyciem.
Zobacz
SimpleDateFormat.setTimeZone(..)
iCalendar.setTimeZone(..)
po szczegółyźródło
stwórz parę klient / serwer, tak aby po wykonaniu klient serwer wysyłał poprawny czas i datę. Następnie klient pyta serwer o godz. GMT, a serwer odsyła prawidłową odpowiedź.
źródło
Użyj właściwości systemu:
źródło
Wykonaj tę linię w MySQL, aby zresetować swoją strefę czasową:
SET @@global.time_zone = '+00:00';
źródło
Łał. Wiem, że to starożytny wątek, ale wszystko, co mogę powiedzieć, to nie wywoływać TimeZone.setDefault () w żadnym kodzie na poziomie użytkownika. To zawsze ustawia strefę czasową dla całej maszyny JVM i prawie zawsze jest to bardzo zły pomysł. Naucz się korzystać z biblioteki joda.time lub nowej klasy DateTime w Javie 8, która jest bardzo podobna do biblioteki joda.time.
źródło
Mam nadzieję, że poniższy kod ci pomoże.
DateFormat formatDate = new SimpleDateFormat(ISO_DATE_TIME_PATTERN); formatDate.setTimeZone(TimeZone.getTimeZone("UTC")); formatDate.parse(dateString);
źródło
Jeśli chcesz uzyskać czas GMT tylko za pomocą intiger: var currentTime = new Date (); var currentYear = '2010' var currentMonth = 10; var currentDay = '30 'var currentHours = '20' var currentMinutes = '20 'var currentSeconds = '00' var currentMilliseconds = '00 '
currentTime.setFullYear(currentYear); currentTime.setMonth((currentMonth-1)); //0is January currentTime.setDate(currentDay); currentTime.setHours(currentHours); currentTime.setMinutes(currentMinutes); currentTime.setSeconds(currentSeconds); currentTime.setMilliseconds(currentMilliseconds); var currentTimezone = currentTime.getTimezoneOffset(); currentTimezone = (currentTimezone/60) * -1; var gmt =""; if (currentTimezone !== 0) { gmt += currentTimezone > 0 ? ' +' : ' '; gmt += currentTimezone; } alert(gmt)
źródło