java.time
Wraz z wydaniem Java SE 8 w marcu 2014 r. przestarzały i podatny na błędy starszy interfejs Data-Czas API (java.util
Typy daty-godziny i ich typ formatowania, SimpleDateFormat
itp.) został zastąpiony przez java.time
, nowoczesny interfejs Data-Time API. poniższa tabela
przedstawia mapowanie typów ANSI SQL za pomocą java.time
typy:
ANSI SQL | Java SE 8 |
---|---|
DATA | Lokalna data |
CZAS | Czas lokalny |
ZNACZNIK CZASOWY | LocalDateTime |
CZAS ZE STREFĄ CZASOWĄ | Czas przesunięcia |
ZNACZNIK CZASOWY Z STREFĄ CZASOWĄ | OffsetDateTime |
Zwróć uwagę, że ZonedDateTime
i Instant
nie są obsługiwane przez żaden sterownik JDBC, podczas gdy niektóre sterowniki, np. PostgreSQL również nie obsługuje OffsetTime
/ TIME [ WITHOUT TIMEZONE ]
. Pamiętaj też, że wszystkie OffsetDateTime
instancje będą musiały być w UTC (mieć przesunięcie 0). Dzieje się tak, ponieważ backend przechowuje je jako UTC.
Jak go używać w JDBC?
Poniżej podano przykładowy kod do wstawienia bieżącego OffsetDateTime
w UTC, do columnfoo
(który ma TIMESTAMP WITH TIMEZONE
typ):
OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();
Instant
reprezentuje chwilowy punkt na osi czasu i jest niezależny od strefy czasowej, tj. ma przesunięcie strefy czasowej o +00:00
godzin.
Poniżej podano przykładowy kod do pobrania OffsetDateTime
z columnfoo
:
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
// Assuming the column index of columnfoo is 1
OffsetDateTime odt = rs.getObject(1, OffsetDateTime.class));
System.out.println(odt);
}
rs.close();
st.close();
Na wypadek, gdybyś musiał przekonwertować OffsetDateTime
w inny z innym przesunięciem:
Jest na to kilka sposobów, ale najczęściej używam OffsetDateTime#withOffsetSameInstant
, aby przekonwertować OffsetDateTime
na inny z innym przesunięciem strefy czasowej, np.
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// A sample OffsetDateTime in UTC.
OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
System.out.println(odt);
OffsetDateTime offsetTimeAtOffset0100 = odt.withOffsetSameInstant(ZoneOffset.of("+02:00"));
System.out.println(offsetTimeAtOffset0100);
// Time at JVM's default timezone offset
ZoneOffset jvmTzOffset = ZonedDateTime.now(ZoneId.systemDefault()).getOffset();
OffsetDateTime offsetTimeAtJvmTzOffset = odt.withOffsetSameInstant(jvmTzOffset);
System.out.println(offsetTimeAtJvmTzOffset);
}
}
Wyjście:
2021-05-29T13:36:15.258076Z
2021-05-29T15:36:15.258076+02:00
2021-05-29T14:36:15.258076+01:00
Kilka punktów związanych z powyższym kodem:
Z
w danych wyjściowych znajduje się znacznik strefy czasowej dla zerowego przesunięcia strefy czasowej. Oznacza Zulu i określaEtc/UTC
strefa czasowa (która ma przesunięcie strefy czasowej+00:00
godzin).- Kod konwertuje
odt
na dwie instancjeOffsetDateTime
- każdy w inny sposób. Pierwsza instancja ma stałe przesunięcie strefy czasowej+02:00
godzin, podczas gdy druga jest z przesunięciem strefy czasowej JVM. Zwróć uwagę, że przesunięcie strefy czasowej miejsca obserwującego DST zmiany według czasu letniego/zimowego. Dlatego, jeśli miejsce przestrzega czasu letniego, zamiast używać stałego przesunięcia strefy czasowej, np.+02:00
godziny; powinniśmy pobrać to z API. - Strefa czasowa mojej JVM to
Europe/London
a obecnie jego przesunięcie to+01:00
godzin.
Dowiedz się więcej o nowoczesnym interfejsie API data-czas z Szlak:Data Godzina .