java.time
With the release of Java SE 8 in March 2014, the outdated and error-prone legacy Date-Time API (java.util
Date-Time types and their formatting type, SimpleDateFormat
etc.) was supplanted by java.time
, the modern Date-Time API*. The following table depicts the mapping of ANSI SQL types with java.time
types:
ANSI SQL |
Java SE 8 |
DATE |
LocalDate |
TIME |
LocalTime |
TIMESTAMP |
LocalDateTime |
TIME WITH TIMEZONE |
OffsetTime |
TIMESTAMP WITH TIMEZONE |
OffsetDateTime |
注意ZonedDateTime
and Instant
任何 JDBC 驱动程序都不支持,而某些驱动程序例如PostgreSQL也不支持OffsetTime
/ TIME [ WITHOUT TIMEZONE ]
。另外,请注意,所有OffsetDateTime
实例必须采用 UTC(偏移量为 0)。这是因为后端将它们存储为 UTC。
如何在 JDBC 中使用它?
下面给出的是插入当前的示例代码OffsetDateTime
在 UTC 中,进入columnfoo
(这是TIMESTAMP WITH TIMEZONE
type):
OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();
An Instant表示时间线上的瞬时点并且独立于时区,即它的时区偏移量为+00:00
hours.
下面给出了一个示例代码来检索OffsetDateTime
from 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);
}
}
Output:
2021-05-29T13:36:15.258076Z
2021-05-29T15:36:15.258076+02:00
2021-05-29T14:36:15.258076+01:00
与上面给出的代码相关的一些要点:
- The
Z
输出中是时区指示符零时区偏移。它代表祖鲁语并指定Etc/UTC
时区(时区偏移量为+00:00
hours).
- 代码转换
odt
分为两个实例OffsetDateTime
- 每个都以不同的方式。第一个实例的固定时区偏移量为+02:00
小时,而第二个是 JVM 的时区偏移。请注意观察地点的时区偏移DST根据夏季/冬季时间而变化。因此,如果一个地方遵守 DST,则不要使用固定的时区偏移,例如+02:00
小时;我们应该从 API 获取它。
- 我的 JVM 的时区是
Europe/London
目前它的偏移量是+01:00
hours.
Learn more about the modern date-time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.