在表格列中从PDT转换为GMT或从PST转换为GMT的日期时间

时间:2018-07-11 08:21:17

标签: oracle date

我一直坚持从数据库列之一中查找并转换日期。我正在使用的数据库是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时必须进行相应处理

谢谢。

2 个答案:

答案 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值将是相同的-即使它们最初相距一个小时。

From the documentation

  

...不明确的日期时间值被认为是该地区的标准时间表示形式

如果您在会话中将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数据类型不提供任何时区信息,因此没有解决方案。