我有一个直接使用 ADO.NET 的 SQL Builder 库。我有一种使用大于或等于运算符创建选择查询的方法,例如:
select *
from book
where book.date_created >= {some date}
我的问题是 {some date} 将始终位于 UTC 时区,但它与 book.date_created 列进行比较,后者是 TIMESTAMP(6) WITH TIME ZONE 列,该列不会位于 UTC 时区。
我可以执行查询,但我的结果不符合时区比较。我的查询是针对 date_created >= x 的所有书籍,但返回的某些结果不大于 x,因为在减去 5 小时的时区后,它们现在小于 x。返回的 IDataRecord DateTime 字段使用 DateTime.SpecifyKind() 转换为 UTC
我可以形成我的查询,使其在 UTC 时区解释 book.date_created 吗?
注意:虽然我很想更改我的 Oracle DB 列以不指定时区,但我无法更改表结构。
编辑:
目前,{some date} 是一个 SQL 参数。它的支持数据类型是一个以 UTC 为时区的 DateTime。作为参数,它是一个 TimestampWithTZ。参数的值是一个 DateTime,其种类也指定为 UTC。
更新:
该问题似乎与我从 IDataRecord 获得的结果集有关。当我关闭 DateTimes 时,我使用 DateTime.SpecifyKind() 将它们置于 UTC 模式。问题是,日期时间显示为 DateTimeKind.Unspecified。从 Unspecified 转换为 UTC 时,它只是删除时区并声明它是 UTC 而不更改基础值。我不确定如何将 IDataRecord 拉入 TimeZone 值。
最佳答案
您需要使用 FROM_TZ
函数将 TIMESTAMP 转换为 TIMESTAMP WITH TIME ZONE。例如,如果您知道您的变量是 UTC 时间 (+0:00):
SELECT *
FROM book
WHERE date_created >= from_tz(<timestamp>, '+0:00');
这是一个示例脚本,显示您描述的行为(您的本地时区应设置为
+1:00
):CREATE TABLE t (tz TIMESTAMP(6) WITH TIME ZONE);
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 +1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 -1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
-- This will return two values instead of one
SELECT *
FROM t
WHERE tz >= to_timestamp('20000101 00:00:00', 'yyyymmdd hh24:mi:ss');
-- This query will return only one row
SELECT *
FROM t
WHERE tz >= from_tz (to_timestamp('20000101 00:00:00',
'yyyymmdd hh24:mi:ss'), '+0:00');