java.time
Med lanseringen av Java SE 8 i mars 2014, det föråldrade och felbenägna äldre Date-Time API (java.util
Datum-tid-typer och deras formateringstyp, SimpleDateFormat
etc.) ersattes av java.time
, det moderna Date-Time API. följande tabell
skildrar mappningen av ANSI SQL-typer med java.time
typer:
ANSI SQL | Java SE 8 |
---|---|
DATUM | LocalDate |
TID | Lokaltid |
TIMESTAMP | LocalDateTime |
TID MED TIDZON | OffsetTime |
TIDSSTÄMPEL MED TIDZON | OffsetDateTime |
Observera att ZonedDateTime
och Instant
stöds inte av någon JDBC-drivrutin medan vissa drivrutiner, t.ex. PostgreSQL stöder inte heller OffsetTime
/ TIME [ WITHOUT TIMEZONE ]
. Observera också att alla OffsetDateTime
instanser måste vara i UTC (ha offset 0). Detta beror på att backend lagrar dem som UTC.
Hur använder man det i JDBC?
Nedan ges en exempelkod för att infoga den aktuella OffsetDateTime
i UTC, till columnfoo
(som är av 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();
En Instant
representerar en momentan punkt på tidslinjen och är oberoende av en tidszon, dvs den har en tidszonförskjutning på +00:00
timmar.
Nedan ges en exempelkod för att hämta en OffsetDateTime
från 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();
Ifall du behöver konvertera en OffsetDateTime
till en annan med en annan offset:
Det finns flera sätt att göra det men jag använder mest OffsetDateTime#withOffsetSameInstant
, för att konvertera en OffsetDateTime
till en annan med en annan tidszonförskjutning, t.ex.
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);
}
}
Utdata:
2021-05-29T13:36:15.258076Z
2021-05-29T15:36:15.258076+02:00
2021-05-29T14:36:15.258076+01:00
Några punkter relaterade till koden ovan:
Z
i utgången finns tidszonsbeteckning för nolltidszonförskjutning. Det står för Zulu och angerEtc/UTC
tidszon (som har tidszonförskjutningen+00:00
timmar).- Koden konverterar
odt
i två instanser avOffsetDateTime
- var och en på olika sätt. Den första instansen är med en fast tidszonförskjutning på+02:00
timmar medan den andra är med tidszonförskjutningen för JVM. Observera att tidszonsförskjutningen för en plats som observerar sommartid ändras per sommar/vintertid. Därför, om en plats observerar sommartid, istället för att använda en fast tidszonförskjutning, t.ex.+02:00
timmar; vi borde hämta det från API:t. - Min JVM:s tidszon är
Europe/London
och för närvarande är dess offset+01:00
timmar.
Läs mer om moderna date-time API a> från Trail:Date Time .