Oracle - 如何*正确*从EST / EDT转换为GMT?

时间:2016-08-17 19:28:59

标签: oracle date datetime timezone

我有一个正在进行某些时区转换的查询。例如,我想将EST时间转换为GMT

对于EDT时间3/13/2016 @2:00 AM(紧接EST-> EDT转换后),我应该获得3/13/2016 7:00:00 AM的GMT时间(verified here为3/13 / 2016 @ 2am)。相反,我使用此查询获得3/13/2016 6:00:00 AM

SELECT NEW_TIME(TO_DATE('2016/3/13 02:00:00 AM', 
               'YYYY/MM/DD HH:MI:SS AM'),'EDT','GMT') 
FROM DUAL;

对于3/13/2016 @1:00AM的EST时间(转换前一秒),我得到的结果似乎正确:

SELECT NEW_TIME(TO_DATE('2016/3/13 01:59:59 AM', 
                        'YYYY/MM/DD HH:MI:SS AM'),'EST','GMT') 
FROM DUAL;

结果:

3/13/2016 6:59:59 AM

我在这里做错了什么?我已经阅读了关于NEW_TIME的Oracle文档,并尝试使用GMT切换EDT / EST(基于他们在页面底部的一个示例),但这给了我更奇怪的结果。

2 个答案:

答案 0 :(得分:2)

您不应使用旧时尚功能X509Certificate2UI.SelectFromCollection,请使用Oracle推荐的FROM_TZDatetime Expressions

一个问题是时区NEW_TIMEEST 没有任何夏令时! EDT总是意味着(最有可能)UTC-05:00,无论冬天是夏天。 EST总是意味着(最有可能)UTC-04:00,无论冬天是夏天。

除了缺少夏令时支持外,EDTEST不明确,请参阅此列表:

EDT

尝试这样,那么无论你的季节如何,你的时间都会自动转换:

SELECT tzabbrev, TZ_OFFSET(tzname), tzname
FROM V$TIMEZONE_NAMES
WHERE tzname IN ('EST', 'EDT') OR tzabbrev IN ('EST', 'EDT')
ORDER BY 1,2;

TZABBREV    TZ_OFFSET(TZNAME)   TZNAME
===============================================
EDT -04:00  America/Detroit
EDT -04:00  US/Eastern
EDT -04:00  US/East-Indiana
EDT -04:00  EST5EDT
EDT -04:00  Canada/Eastern
EDT -04:00  America/Toronto
EDT -04:00  America/Thunder_Bay
EDT -04:00  America/Santo_Domingo
EDT -04:00  America/Pangnirtung
EDT -04:00  America/Nipigon
EDT -04:00  America/New_York
EDT -04:00  America/Nassau
EDT -04:00  America/Montreal
EDT -04:00  America/Louisville
EDT -04:00  America/Kentucky/Monticello
EDT -04:00  America/Kentucky/Louisville
EDT -04:00  America/Iqaluit
EDT -04:00  America/Indianapolis
EDT -04:00  America/Indiana/Winamac
EDT -04:00  America/Indiana/Vincennes
EDT -04:00  America/Indiana/Vevay
EDT -04:00  America/Indiana/Petersburg
EDT -04:00  America/Indiana/Marengo
EDT -04:00  US/Michigan
EDT -04:00  America/Fort_Wayne
EDT -04:00  America/Grand_Turk
EDT -04:00  America/Indiana/Indianapolis
EDT -05:00  America/Jamaica
EDT -05:00  America/Indiana/Tell_City
EDT -05:00  Jamaica
EDT -05:00  America/Cancun
EDT -05:00  America/Port-au-Prince
EST +09:30  Australia/Broken_Hill
EST +09:30  Australia/Yancowinna
EST +10:00  Australia/Canberra
EST +10:00  Australia/Brisbane
EST +10:00  Australia/ACT
EST +10:00  Australia/Currie
EST +10:00  Australia/Hobart
EST +10:00  Australia/Lindeman
EST +10:00  Australia/Melbourne
EST +10:00  Australia/NSW
EST +10:00  Australia/Queensland
EST +10:00  Australia/Tasmania
EST +10:00  Australia/Sydney
EST +10:00  Australia/Victoria
EST +10:30  Australia/Lord_Howe
EST +10:30  Australia/LHI
EST +11:00  Antarctica/Macquarie
EST -03:00  America/Moncton
EST -04:00  America/Antigua
EST -04:00  America/Detroit
EST -04:00  America/Fort_Wayne
EST -04:00  America/Grand_Turk
EST -04:00  America/Indiana/Indianapolis
EST -04:00  America/Indiana/Marengo
EST -04:00  America/Indiana/Petersburg
EST -04:00  America/Indiana/Vevay
EST -04:00  America/Indiana/Vincennes
EST -04:00  America/Indiana/Winamac
EST -04:00  America/Indianapolis
EST -04:00  America/Iqaluit
EST -04:00  America/Kentucky/Louisville
EST -04:00  America/Kentucky/Monticello
EST -04:00  America/Louisville
EST -04:00  America/Montreal
EST -04:00  America/Nassau
EST -04:00  America/New_York
EST -04:00  America/Nipigon
EST -04:00  America/Pangnirtung
EST -04:00  America/Santo_Domingo
EST -04:00  America/Thunder_Bay
EST -04:00  America/Toronto
EST -04:00  Canada/Eastern
EST -04:00  EST5EDT
EST -04:00  US/East-Indiana
EST -04:00  US/Eastern
EST -04:00  US/Michigan
EST -05:00  US/Central
EST -05:00  Jamaica
EST -05:00  America/Cancun
EST -05:00  America/Cayman
EST -05:00  America/Chicago
EST -05:00  America/Coral_Harbour
EST -05:00  America/Indiana/Knox
EST -05:00  America/Indiana/Tell_City
EST -05:00  America/Jamaica
EST -05:00  America/Knox_IN
EST -05:00  America/Atikokan
EST -05:00  America/Menominee
EST -05:00  America/Merida
EST -05:00  America/Panama
EST -05:00  America/Port-au-Prince
EST -05:00  America/Rankin_Inlet
EST -05:00  America/Resolute
EST -05:00  CST
EST -05:00  EST
EST -05:00  US/Indiana-Starke
EST -06:00  America/Managua
EST -06:00  America/Cambridge_Bay

答案 1 :(得分:-1)

我最终使用了:

SELECT SYSDATE+(SUBSTR(TO_CHAR(SYSTIMESTAMP, 'TZR'),2,2))/24  
FROM DUAL;

其中(SUBSTR(TO_CHAR(SYSTIMESTAMP, 'TZR'),2,2))为您提供utc时间的当前偏移量。我同意FROM_TZ在时区存在的许多边缘情况下可能更准确但我们真的在寻找将这个嵌入到视图中时能够快速计算的东西。

要在区域之间正确转换,我只需将当前偏移量添加到我需要转换的任何时间:

DECLARE 
l_convert_me_to_utc DATE := TO_DATE('9/12/2016 1:00:00 PM','MM/DD/YYYY HH12:MI:SS AM');
l_converted DATE;
BEGIN
    l_converted:=(l_convert_me_to_utc+(SUBSTR(TO_CHAR(SYSTIMESTAMP, 'TZR'),2,2))/24);
    DBMS_OUTPUT.put_line ('UTC TIME IS: '||TO_CHAR(l_converted, 'MM/DD/YYYY HH12:MI:SS AM'));    
END;

UTC TIME IS: 09/12/2016 05:00:00 PM

这是有道理的,因为我现在在EDT的纽约TZ与UTC的-4偏移

编辑:根据下面的评论,这实际上只有在您将OS SYSDATE现在转换为UTC时才有效。如果它是某个其他时区或过去或未来的某个时间,那么这不起作用。我的最终逻辑比你上面看到的更复杂。对于我的应用程序和更复杂的逻辑(从现在到2100年检查具有所有TZ切换日期的表),这确实有效。只是不要拿走我上面的内容,并假设它完全按原样将事物转换为UTC。