我使用的是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应用额外的逻辑。
如有任何帮助,不胜感激。
2条答案
按热度按时间agxfikkp1#
您可以直接将
p_date
定义为UTC时间:或者在声明中:
另一种可能是隐式使用
SESSIONTIMEZONE
,尽管我不推荐这样做:3npbholx2#
“2013年的夏令时从3月10日星期日凌晨2点开始。”
... which is correct,您可以看到UTC等效日期/时间的情况如下:
| 运输系统|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”来转换。
不,不应该。恐怕你问题的前提是错的。
您正在进行的转换得到了正确的结果:
| 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_TZ
和AT TIME ZONE
,正如Wernfried所展示的那样。