在数据库中以 AEST 时区存储日期
Store date in AEST timezone in database
我们在 oracle 数据库中有两个表,如下所示,
表 A => 列 DateA(类型 DATE)
TableB => 列 DateB(类型 DATE)
TableA 中的 DateA 列具有以 UTC 格式存储的日期。
TableB 中的 DateB 列的日期存储在 AEST 中。
当我检查这些表中存储日期的代码(在 java 中)时,两者都只是实例化 Date 类型,如下所示。
现在日期 = 新日期();
当他们使用相同的代码时,他们如何在不同的时区设置日期?
我想知道其他地方是否还有其他配置?
请多多指教。最后,我需要更新代码,以便所有日期都存储在 AEST 中。
DateA column in TableA has dates stored in UTC. DateB column in TableB has dates stored in AEST.
不,没有列以 UTC 或 AEST 格式存储。 Oracle 数据库中的 DATE
类型仅存储日期和时间。该数据类型故意缺少任何时区或与 UTC 的偏移量的概念。您在该列中输入的任何日期和时间都会被保存,但如果没有 zone/offset,我们将无法确定时刻(时间线上的一个点)。
Date now = new Date();
切勿在 Java 中使用 Date
class。这些可怕的 classes 是由不了解日期时间处理的人设计的。这些 classes 现在是遗留的,多年前被 JSR 310 中定义的现代 java.time classes 取代。
Ultimately, I need to update code so all dates are stored in AEST.
由于您在现有存储数据中丢失了 zone/offset 的上下文,我看不出有什么方法可以清理这些混乱。
但是,仅供参考,我可以展示存储此类数据的正确方法。
首先,将您的数据库列定义为类似于 SQL 标准类型 TIMESTAMP WITH TIME ZONE
的数据类型(相对于 WITHOUT
)。根据我对 this doc 的阅读,对于 Oracle Database 21 那将是同名的 TIMESTAMP WITH TIME ZONE
.
在Java中指定所需的时区。
AEST
不是时区。它指示是否启用夏令时 (DST)。切勿在您的业务逻辑和存储的数据中使用此类值。在 Continent/Region
.
的新格式中仅使用 real time zone names
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
捕获与 UTC 零小时-分钟-秒的偏移量的当前时刻。
Instant instant = Instant.now() ;
适应您的时区。
ZonedDateTime zdt = instant.atZone( z ) ;
不幸的是,SQL 标准不处理时区。所以我们必须转换为偏移量而不是区域,以便与数据库交换值。
OffsetDateTime odt = zdt.toOffsetDateTime() ;
通过 JDBC 4.2 或更高版本。
myPreparedStatement.setObject( … , odt ) ;
检索。
OffsetDateTime odt = myResultSet( … , OffsetDateTime.class ) ;
适应您的时区。
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
我们在 oracle 数据库中有两个表,如下所示,
表 A => 列 DateA(类型 DATE)
TableB => 列 DateB(类型 DATE)
TableA 中的 DateA 列具有以 UTC 格式存储的日期。 TableB 中的 DateB 列的日期存储在 AEST 中。
当我检查这些表中存储日期的代码(在 java 中)时,两者都只是实例化 Date 类型,如下所示。
现在日期 = 新日期();
当他们使用相同的代码时,他们如何在不同的时区设置日期? 我想知道其他地方是否还有其他配置?
请多多指教。最后,我需要更新代码,以便所有日期都存储在 AEST 中。
DateA column in TableA has dates stored in UTC. DateB column in TableB has dates stored in AEST.
不,没有列以 UTC 或 AEST 格式存储。 Oracle 数据库中的 DATE
类型仅存储日期和时间。该数据类型故意缺少任何时区或与 UTC 的偏移量的概念。您在该列中输入的任何日期和时间都会被保存,但如果没有 zone/offset,我们将无法确定时刻(时间线上的一个点)。
Date now = new Date();
切勿在 Java 中使用 Date
class。这些可怕的 classes 是由不了解日期时间处理的人设计的。这些 classes 现在是遗留的,多年前被 JSR 310 中定义的现代 java.time classes 取代。
Ultimately, I need to update code so all dates are stored in AEST.
由于您在现有存储数据中丢失了 zone/offset 的上下文,我看不出有什么方法可以清理这些混乱。
但是,仅供参考,我可以展示存储此类数据的正确方法。
首先,将您的数据库列定义为类似于 SQL 标准类型 TIMESTAMP WITH TIME ZONE
的数据类型(相对于 WITHOUT
)。根据我对 this doc 的阅读,对于 Oracle Database 21 那将是同名的 TIMESTAMP WITH TIME ZONE
.
在Java中指定所需的时区。
AEST
不是时区。它指示是否启用夏令时 (DST)。切勿在您的业务逻辑和存储的数据中使用此类值。在 Continent/Region
.
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
捕获与 UTC 零小时-分钟-秒的偏移量的当前时刻。
Instant instant = Instant.now() ;
适应您的时区。
ZonedDateTime zdt = instant.atZone( z ) ;
不幸的是,SQL 标准不处理时区。所以我们必须转换为偏移量而不是区域,以便与数据库交换值。
OffsetDateTime odt = zdt.toOffsetDateTime() ;
通过 JDBC 4.2 或更高版本。
myPreparedStatement.setObject( … , odt ) ;
检索。
OffsetDateTime odt = myResultSet( … , OffsetDateTime.class ) ;
适应您的时区。
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;