我们在oracle存储的所有日期都在EDT(夏季)和EST(冬季)。我需要一种方法将该日期转换为UTC / GMT。
转换应该基于db日期而不是服务器本地TZ。 换句话说,如果结果集中的日期介于:
之间"11/02/2014 02:00:00" ---> "03/08/2015 01:59:59": TZ offset = "-0500"
"03/08/2015 02:00:00" ---> "11/01/2015 01:59:59": TZ offset = "-0400".
前几年也一样。 有解决方案吗?
答案 0 :(得分:0)
假设some_date_column
实际上是一个日期列,那么您可以使用强制转换(从日期到时间戳)将其转换为带时区的时间戳,将the from_tz
function转换为具有EST / EDT更改的区域定义:
with t (some_date_column) as (
select to_date('11/02/2014 02:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('03/08/2014 01:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('03/08/2015 03:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/01/2015 00:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/01/2015 01:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/02/2015 02:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
)
select t.some_date_column,
cast(t.some_date_column as timestamp) as some_timestamp,
from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
as some_timestamp_tz
from t;
SOME_DATE_COLUMN SOME_TIMESTAMP SOME_TIMESTAMP_TZ
------------------- ------------------- ---------------------------
11/02/2014 02:00:00 11/02/2014 02:00:00 11/02/2014 02:00:00 -05:00
03/08/2014 01:59:59 03/08/2014 01:59:59 03/08/2014 01:59:59 -05:00
03/08/2015 03:00:00 03/08/2015 03:00:00 03/08/2015 03:00:00 -04:00
11/01/2015 00:59:59 11/01/2015 00:59:59 11/01/2015 00:59:59 -04:00
11/01/2015 01:59:59 11/01/2015 01:59:59 11/01/2015 01:59:59 -05:00
11/02/2015 02:00:00 11/02/2015 02:00:00 11/02/2015 02:00:00 -05:00
这与你问题中的范围并不完全一致。当你从EST转到EDT时没有02:00,所以我在演示CTE中使用了03:00;当你从EDT转到EST的另一条路时,01:00到02:00之间的时间间隔(有点)重复,那个小时的平时偏移是不明确的,Oracle选择将其视为-05 :00而不是-04:00。
如果您希望UTC相当于EST / EDT时间,那么您可以使用at time zone
,并可选择强制转换为日期:
...
select t.some_date_column,
from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
at time zone 'UTC' as utc_timestamp_tz,
cast(from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
at time zone 'UTC' as date) as utc_date
from t;
SOME_DATE_COLUMN UTC_TIMESTAMP_TZ UTC_DATE
------------------- --------------------------- -------------------
11/02/2014 02:00:00 11/02/2014 07:00:00 +00:00 11/02/2014 07:00:00
03/08/2014 01:59:59 03/08/2014 06:59:59 +00:00 03/08/2014 06:59:59
03/08/2015 03:00:00 03/08/2015 07:00:00 +00:00 03/08/2015 07:00:00
11/01/2015 00:59:59 11/01/2015 04:59:59 +00:00 11/01/2015 04:59:59
11/01/2015 01:59:59 11/01/2015 06:59:59 +00:00 11/01/2015 06:59:59
11/02/2015 02:00:00 11/02/2015 07:00:00 +00:00 11/02/2015 07:00:00
如果原始列是时间戳(没有时区信息)而不是日期,那么您可以跳过从日期到时间戳的第一个强制转换,但仍然使用from_tz
来指定它的原始区域。