Oracle从GMT转换为EST和EDT

ijxebb2r  于 2022-12-26  发布在  Oracle
关注(0)|答案(2)|浏览(130)

我使用的是Oracle 19 c。
我需要将日期从GMT转换为EST和EDT。
我使用以下方法:

1. Get the destination time zone abbreviation for the p_date variable: 

DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');

SELECT TO_CHAR(FROM_TZ(CAST (&p_date AS TIMESTAMP), 'America/New_York'), 'TZD') INTO v_tzabbrev FROM DUAL; 

Where:
  p_date:  is the date to be converted.
  v_tzname:  is the time zone name, such as America/New_York
  v_tzabbrev:  is the time zone abbreviation, such as 'EDT' or "EST" based on whether the date is during Daylight Saving Time or not

2. Convert the p_date using the time zone abbreviation obtained in #1

 SELECT NEW_TIME(p_date, 'GMT', v_tzabbrev) INTO v_date FROM DUAL;

这似乎起作用了。但是,我相信缺陷在于它是使用格林尼治标准时间日期来确定目的地时区缩写,这是不准确的。
例如,如果p_date在UTC中是'03/11/2013 02:22:21',而我需要将其转换为'America/New_York',则步骤#1将返回'EDT',但在东部时间中该日期实际上是'03/10/2013 21:22:21',这是夏令时开始之前的日期。
2013年的夏令时从3月10日星期日凌晨2点开始。
因此,我似乎需要一种方法来获取GMT值,并首先确定其在东部的新日期,然后根据新日期是EDT还是EST应用额外的逻辑。
如有任何帮助,不胜感激。

agxfikkp

agxfikkp1#

您可以直接将p_date定义为UTC时间:

DEFINE p_date TO_TIMESTAMP_TZ('03/11/2013 02:22:21 UTC', 'MM/DD/YYYY HH24:MI:SS TZR');

SELECT TO_CHAR((&p_date AT TIME ZONE 'America/New_York'), 'TZD') 
INTO v_tzabbrev 
FROM DUAL;

或者在声明中:

DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');

SELECT TO_CHAR((FROM_TZ(CAST(&p_date AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/New_York'), 'TZD') 
INTO v_tzabbrev 
FROM DUAL;

另一种可能是隐式使用SESSIONTIMEZONE,尽管我不推荐这样做:

DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');
ALTER SESSION SET TIME ZONE = 'UTC';

SELECT TO_CHAR((CAST(&p_date AS TIMESTAMP WITH TIME ZONE) AT TIME ZONE 'America/New_York'), 'TZD') 
INTO v_tzabbrev 
FROM DUAL;
3npbholx

3npbholx2#

“2013年的夏令时从3月10日星期日凌晨2点开始。”
... which is correct,您可以看到UTC等效日期/时间的情况如下:

-- get New York DST start time as UTC
with cte (ts) as (
  select timestamp '2013-03-10 01:59:59 America/New_York' from dual
  union all
  select timestamp '2013-03-10 03:00:00 America/New_York' from dual
)
select ts, to_char(ts, 'TZD') as tzd, ts at time zone 'UTC' as ts_utc
from cte

| 运输系统|TZD| TS_UTC时间|
| - ------|- ------|- ------|
| 2013年3月10日01:59:59美洲/约克|EST技术|协调世界时2013年3月10日06:59:59|
| 2013-03-10 03:00:00美洲/约克|电涡流探伤|协调世界时2013年3月10日07:00:00|
但这个日期在东部实际上是“03/10/2013 21:22:21”,这是在夏令时开始之前。
不,不是,是夏令时开始后。
所以,它实际上应该用“EST”来转换。
不,不应该。恐怕你问题的前提是错的。
您正在进行的转换得到了正确的结果:

-- get UTC timestamp as New York
with cte (ts) as (
  select timestamp '2013-03-11 02:22:21 UTC' from dual
)
select ts as ts_utc, ts at time zone 'America/New_YORK' as ts, to_char(ts at time zone 'America/New_York', 'TZD') as tzd
from cte

| TS_UTC时间|运输系统|TZD|
| - ------|- ------|- ------|
| 协调世界时2013年3月11日02:22:21| 2013年3月10日22:22:21美洲/约克|电涡流探伤|
fiddle
2013-03-11 02:22:21 UTC是 * 之后 * 2013-03-10 01:59:59 America/New_约克,因为它是UTC中的第二天,并且是纽约DST切换发生之后的19小时。换句话说,2013-03-11 02:22:21 UTC是2012-03-10 07:00:00 UTC之后的19小时,这是上面第一个查询中EDT开始时间的UTC等效值。
您似乎将UTC值中的日期与当年在美国应用DST的日期混淆了。
因为the NEW_TIME() function是有限的,所以我更愿意使用FROM_TZAT TIME ZONE,正如Wernfried所展示的那样。

相关问题