我正在开发一个包含数据库时间戳记的程序。 db time设置在EST中设置。我已经看到很多关于从一个时区转换为另一个时区的文章,但是有没有办法从EST转换为用户所在的任何时区?
答案 0 :(得分:0)
Oracle数据库中有两个时区设置:数据库的和会话的。这些可以不同。您可以通过以下内容找到这些内容:
select dbtimezone db, sessiontimezone sess from dual;
DB SESS
------------------------------ ------------------------------
+00:00 Europe/London
alter session set time_zone = 'Australia/Perth';
select dbtimezone db, sessiontimezone sess from dual;
DB SESS
------------------------------ ------------------------------
+00:00 Australia/Perth
您可以使用at time zone
子句将时间戳从一个时区转换为另一个时区。例如:
alter session set time_zone = 'Europe/London';
select systimestamp server,
systimestamp at time zone sessiontimezone sess,
systimestamp at time zone 'Asia/Calcutta' india,
current_timestamp curr_ts
from dual;
SERVER SESS INDIA CURR_TS
----------------------------------- ---------------------------------------- ---------------------------------------- ----------------------------------------
28-AUG-18 08.46.59.104889 -07:00 28-AUG-18 16.46.59.104889 EUROPE/LONDON 28-AUG-18 21.16.59.104889 ASIA/CALCUTTA 28-AUG-18 16.46.59.104899 EUROPE/LONDON
注意:systimestamp返回服务器的日期,时间和时区。这可能与DBTIMEZONE
不同! Current_timestamp是会话的时区。
此转换的确切工作方式取决于您存储值的方式。
共有三种时间戳数据类型:
普通的旧时间戳没有时区信息。因此,您需要知道您的应用程序将其存储在哪个TZ!添加at time zone
子句返回的时间与添加的时区相同。
带有时区存储的时间戳按原样保留时区。使用at time zone
返回转换为提供的时区的日期。
本地时区将数据标准化为数据库的时区。查询它们时,数据库会将它们转换为会话时区。使用at time zone
返回转换为提供的时区的日期。
create table t (
ts timestamp,
ts_tz timestamp with time zone,
ts_ltz timestamp with local time zone
);
insert into t values (
timestamp '2018-01-01 00:00:00', timestamp '2018-01-01 00:00:00 UTC', timestamp '2018-01-01 00:00:00 UTC'
);
insert into t values (
timestamp '2018-01-01 00:00:00', timestamp '2018-01-01 00:00:00 America/Denver', timestamp '2018-01-01 00:00:00 America/Denver'
);
select * from t;
TS TS_TZ TS_LTZ
---------------------------------------- ---------------------------------------- ----------------------------------------
01-JAN-18 00.00.00.000000 01-JAN-18 00.00.00.000000 UTC 01-JAN-18 00.00.00.000000
01-JAN-18 00.00.00.000000 01-JAN-18 00.00.00.000000 AMERICA/DENVER 01-JAN-18 07.00.00.000000
alter session set time_zone = 'Asia/Calcutta';
select * from t;
TS TS_TZ TS_LTZ
---------------------------------------- ---------------------------------------- ----------------------------------------
01-JAN-18 00.00.00.000000 01-JAN-18 00.00.00.000000 UTC 01-JAN-18 05.30.00.000000
01-JAN-18 00.00.00.000000 01-JAN-18 00.00.00.000000 AMERICA/DENVER 01-JAN-18 12.30.00.000000
select ts at time zone sessiontimezone ts,
ts_tz at time zone sessiontimezone ts_tz,
ts_ltz at time zone sessiontimezone ts_ltz
from t;
TS TS_TZ TS_LTZ
---------------------------------------- ---------------------------------------- ----------------------------------------
01-JAN-18 00.00.00.000000 ASIA/CALCUTTA 01-JAN-18 05.30.00.000000 ASIA/CALCUTTA 01-JAN-18 05.30.00.000000 ASIA/CALCUTTA
01-JAN-18 00.00.00.000000 ASIA/CALCUTTA 01-JAN-18 12.30.00.000000 ASIA/CALCUTTA 01-JAN-18 12.30.00.000000 ASIA/CALCUTTA
如果将值存储在date
中,则相同的规则适用于纯时间戳记。
答案 1 :(得分:0)
如果我正确理解您的问题,那么当前存储的只是一个时间戳。您知道时间戳记应该在EST中;数据库不知道。
(顺便说一下,为什么要使用EST?您是否不需要一个带有夏时制时间偏移的时区?或者换句话说,您是否100%确定它是EST而不是EDT?)
理想地,如果目的是在本地时区工作,则该列的数据类型不应为timestamp
或timestamp with time zone
;相反,它应该是timestamp with local time zone
。每当以这种数据类型输入数据时,您仅提供一个时区。 Oracle认为这是您会话的时区;它将其转换为服务器时区并存储。没有存储时区信息,但列类型有意义。检索到相同的数据后,它将转换为调用者的时区。
在您的情况下,如果时间戳记不带时区存储在数据类型timestamp
的列中,则在检索数据时需要做两件事。首先,您需要让Oracle知道时间戳是在时区EST
中(或其实际应该在的其他时区中)。然后-在此步骤之后-您可以将其转换为带有 local 时区的时间戳;那么行为就变得与理想安排中的行为相同,在理想安排中,列从一开始就是timestamp with local time zone
数据类型。
下图显示了两个步骤。
这是您的基表-带有timestamp
类型的单列和单行。您知道时间戳记是时区EST;数据库没有。
create table tbl(ts timestamp);
insert into tbl(ts)
values (timestamp '2018-08-24 13:50:23.392302000');
这是我建议的解决方案。只有最后一列才是您真正需要的。我显示第二列来说明所需的中间步骤。请注意第二列与第一列之间的差异:第二列的时区显示在末尾(-05:00)。另请注意,第三列将取决于我(或您或任何其他人的)会话时区。矿井(目前是夏令时)比美国东部标准时间晚两个小时;这将比美国东部时间晚三小时。我在美国西海岸。
select ts,
from_tz(ts, 'EST') ts_with_time_zone,
cast(from_tz(ts, 'EST') as timestamp with local time zone) ts_in_local_time_zone
from tbl;
TS TS_WITH_TIME_ZONE TS_IN_LOCAL_TIME_ZONE
----------------------------- ------------------------------------ -----------------------------
2018-08-24 13:50:23.392302000 2018-08-24 13:50:23.392302000 -05:00 2018-08-24 11:50:23.392302000