java.time
С пускането на Java SE 8 през март 2014 г., остарелият и податлив на грешки наследен API за дата-време (java.util
Типове дата-час и техният тип форматиране, SimpleDateFormat
и т.н.) беше заменен от java.time
, съвременният API за дата-време. Следната таблица
изобразява съпоставянето на ANSI SQL типове с java.time
видове:
ANSI SQL | Java SE 8 |
---|---|
ДАТА | LocalDate |
ВРЕМЕ | Местно време |
TIMESTAMP | LocalDateTime |
ВРЕМЕ С ЧАСОВА ЗОНА | OffsetTime |
ЧАСОВА ПЕЧАТА С ЧАСОВА ЗОНА | OffsetDateTime |
Имайте предвид, че ZonedDateTime
и Instant
не се поддържат от нито един JDBC драйвер, докато някои драйвери, напр. PostgreSQL също не поддържа OffsetTime
/ TIME [ WITHOUT TIMEZONE ]
. Също така имайте предвид, че всички OffsetDateTime
екземплярите трябва да са в UTC (да имат отместване 0). Това е така, защото бекенда ги съхранява като UTC.
Как да го използвам в JDBC?
По-долу е даден примерен код за вмъкване на текущия OffsetDateTime
в UTC, в columnfoo
(което е от TIMESTAMP WITH TIMEZONE
тип):
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
представлява моментна точка на времевата линия и е независима от часова зона, т.е. има изместване на часовата зона от +00:00
часа.
По-долу е даден примерен код за извличане на OffsetDateTime
от 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();
Само в случай, че трябва да конвертирате OffsetDateTime
в друг с различно изместване:
Има няколко начина да го направя, но най-вече използвам OffsetDateTime#withOffsetSameInstant
, за да конвертирате OffsetDateTime
в друг с различно изместване на часовата зона, напр.
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);
}
}
Изход:
2021-05-29T13:36:15.258076Z
2021-05-29T15:36:15.258076+02:00
2021-05-29T14:36:15.258076+01:00
Някои точки, свързани с кода, даден по-горе:
Z
в изхода е индикаторът на часовата зона за изместване на нулева часова зона. Той означава Zulu и определяEtc/UTC
часова зона (която има изместване на часовата зона от+00:00
часа).- Кодът преобразува
odt
в два екземпляра наOffsetDateTime
- всеки по различен начин. Първият екземпляр е с фиксирано изместване на часовата зона от+02:00
часа, докато вторият е с изместване на часовата зона на JVM. Имайте предвид, че изместването на часовата зона на място, което наблюдава DST промени според лятно/зимно часово време. Следователно, ако дадено място спазва DST, вместо да се използва фиксирано изместване на часовата зона, напр.+02:00
часа; трябва да го получим от API. - Часовата зона на моята JVM е
Europe/London
и в момента нейното изместване е+01:00
часа.
Научете повече за модерния API за дата и време от Пътека:Дата и час .