我一直坚持从数据库列之一中查找并转换日期。我正在使用的数据库是Oracle。
“我的数据库”列根据输入的年份将数据保存在PST或PDT中。
例如-在美国,本地时间从三月的第二个星期日的02:00 LST到PST到PDT,并且在第一个星期日的02:00 LDT变成01:00 LST在十一月。
因此,在我的目标中,我还有一栏将以GMT格式存储日期。
因此,请帮助我处理这种情况并将结果从“源”存储到目标。
源表:
Request_ID, Requested_by, Added_Day
目标表:
Request_ID, Requested_by, Added_Day, Added_Day_INGMT
如上例中所述,源中的“添加的日期”将基于添加的日期在PDT和PST中包含数据。
并且在Target中,我希望将相应的Added_day在将其转换为GMT后保存在Applied_Day_INGMT中。
请帮助我做到这一点。我很无能为力,因为同一列中包含PDT和PST的数据,并且在将其转换为GMT时必须进行相应处理
谢谢。
答案 0 :(得分:3)
如果您确实想将数据复制到新表中,则可以执行以下操作:
insert into target (request_id, requested_by, added_day, added_day_ingmt)
select request_id, requested_by, added_day,
cast(sys_extract_utc(from_tz(cast(added_day as timestamp), 'America/Los_Angeles')) as date)
from source;
与@Wernfried显示的转换相同(除了向西海岸移动);我在末尾做了一个明确的日期转换,尽管如果目标列是一个日期,因为它会被隐式转换,这实际上不是必需的。
快速演示:
create table source (request_id, requested_by, added_day) as
select 1, 'Anon', cast(timestamp '2017-11-05 01:00:00' as date) from dual
union all select 2, 'Anon', cast(timestamp '2017-11-05 01:59:59' as date) from dual
union all select 3, 'Anon', cast(timestamp '2017-11-05 02:00:00' as date) from dual
union all select 4, 'Anon', cast(timestamp '2017-11-05 02:59:59' as date) from dual
union all select 5, 'Anon', cast(timestamp '2017-11-05 03:00:00' as date) from dual
union all select 6, 'Anon', cast(timestamp '2018-03-11 00:59:59' as date) from dual
union all select 7, 'Anon', cast(timestamp '2018-03-11 01:00:00' as date) from dual
union all select 8, 'Anon', cast(timestamp '2018-03-11 01:59:59' as date) from dual
union all select 9, 'Anon', cast(timestamp '2018-03-11 03:00:00' as date) from dual;
create table target (request_id number(25), requested_by varchar2(30), added_day date,
added_day_ingmt date);
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF1';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF1 TZH:TZM';
您可以通过以下方式查看转换步骤:
select request_id, requested_by, added_day,
from_tz(cast(added_day as timestamp), 'America/Los_Angeles'),
from_tz(cast(added_day as timestamp), 'America/Los_Angeles') at time zone 'UTC',
sys_extract_utc(from_tz(cast(added_day as timestamp), 'America/Los_Angeles')),
cast(sys_extract_utc(from_tz(cast(added_day as timestamp), 'America/Los_Angeles')) as date)
from source;
REQUEST_ID REQU ADDED_DAY FROM_TZ(CAST(ADDED_DAYASTIME FROM_TZ(CAST(ADDED_DAYASTIME SYS_EXTRACT_UTC(FROM_ CAST(SYS_EXTRACT_UT
---------- ---- ------------------- ---------------------------- ---------------------------- --------------------- -------------------
1 Anon 2017-11-05 01:00:00 2017-11-05 01:00:00.0 -08:00 2017-11-05 09:00:00.0 +00:00 2017-11-05 09:00:00.0 2017-11-05 09:00:00
2 Anon 2017-11-05 01:59:59 2017-11-05 01:59:59.0 -08:00 2017-11-05 09:59:59.0 +00:00 2017-11-05 09:59:59.0 2017-11-05 09:59:59
3 Anon 2017-11-05 02:00:00 2017-11-05 02:00:00.0 -08:00 2017-11-05 10:00:00.0 +00:00 2017-11-05 10:00:00.0 2017-11-05 10:00:00
4 Anon 2017-11-05 02:59:59 2017-11-05 02:59:59.0 -08:00 2017-11-05 10:59:59.0 +00:00 2017-11-05 10:59:59.0 2017-11-05 10:59:59
5 Anon 2017-11-05 03:00:00 2017-11-05 03:00:00.0 -08:00 2017-11-05 11:00:00.0 +00:00 2017-11-05 11:00:00.0 2017-11-05 11:00:00
6 Anon 2018-03-11 00:59:59 2018-03-11 00:59:59.0 -08:00 2018-03-11 08:59:59.0 +00:00 2018-03-11 08:59:59.0 2018-03-11 08:59:59
7 Anon 2018-03-11 01:00:00 2018-03-11 01:00:00.0 -08:00 2018-03-11 09:00:00.0 +00:00 2018-03-11 09:00:00.0 2018-03-11 09:00:00
8 Anon 2018-03-11 01:59:59 2018-03-11 01:59:59.0 -08:00 2018-03-11 09:59:59.0 +00:00 2018-03-11 09:59:59.0 2018-03-11 09:59:59
9 Anon 2018-03-11 03:00:00 2018-03-11 03:00:00.0 -07:00 2018-03-11 10:00:00.0 +00:00 2018-03-11 10:00:00.0 2018-03-11 10:00:00
并运行上面的插入操作将插入九行,这将为您提供:
select * from target;
REQUEST_ID REQUESTED_BY ADDED_DAY ADDED_DAY_INGMT
---------- ------------------------------ ------------------- -------------------
1 Anon 2017-11-05 01:00:00 2017-11-05 09:00:00
2 Anon 2017-11-05 01:59:59 2017-11-05 09:59:59
3 Anon 2017-11-05 02:00:00 2017-11-05 10:00:00
4 Anon 2017-11-05 02:59:59 2017-11-05 10:59:59
5 Anon 2017-11-05 03:00:00 2017-11-05 11:00:00
6 Anon 2018-03-11 00:59:59 2018-03-11 08:59:59
7 Anon 2018-03-11 01:00:00 2018-03-11 09:00:00
8 Anon 2018-03-11 01:59:59 2018-03-11 09:59:59
9 Anon 2018-03-11 03:00:00 2018-03-11 10:00:00
尽管如此,您无法解决PDT-> PST切换过程中时间的歧义性,因为该时间重复了-如果没有原始时区信息,您将不知道两个可能的GMT / UTC中哪个时间与那个小时实际上是指。
证明这种模糊性:
with t (tsz) as (
select timestamp '2017-11-05 01:30:00 America/Los_Angeles PDT' from dual
union all select timestamp '2017-11-05 01:30:00 America/Los_Angeles PST' from dual
)
select tsz, cast(tsz as date), from_tz(cast(tsz as timestamp), 'America/Los_Angeles')
from t;
TSZ CAST(TSZASDATE) FROM_TZ(CAST(TSZASTIMESTAMP)
---------------------------- ------------------- ----------------------------
2017-11-05 01:30:00.0 -07:00 2017-11-05 01:30:00 2017-11-05 01:30:00.0 -08:00
2017-11-05 01:30:00.0 -08:00 2017-11-05 01:30:00 2017-11-05 01:30:00.0 -08:00
从PDT或PST中的01:30开始,将转换为01:30的日期或时间戳,而没有时区信息;将晒日光转换为Oracle必须选择使用的时区。无论最初的DST情况如何,您最终都将获得PST值-在您的情况下,最终的UTC值将是相同的-即使它们最初相距一个小时。
...不明确的日期时间值被认为是该地区的标准时间表示形式
如果您在会话中将ERROR_ON_OVERLAP_TIME
设置为TRUE
,则对那些模棱两可的值会出错。
答案 1 :(得分:1)
您可以这样添加虚拟列:
Added_Day_INGMT DATE GENERATED ALWAYS AS (SYS_EXTRACT_UTC(FROM_TZ(CAST(Added_Day AS TIMESTAMP), 'America/New_York'))) VIRTUAL
但是,Alex Poole表示的时间将无效。对于此类时间戳,由于DATE
数据类型不提供任何时区信息,因此没有解决方案。