为什么Oracle的to_timestamp_tz会返回错误的时间和/或时区?

时间:2016-12-19 18:11:36

标签: oracle timezone

之前我曾使用过时区的Oracle时间戳,但这次我将值作为字符串并尝试将它们加载到数据库中。

转换字符串时,我最终得到数据库时区中的值。这很奇怪,但如果它相应地调整了时间但却没有。见下文:

SELECT TO_CHAR(systimestamp AT TIME ZONE 'Canada/Pacific', 
                                               'HH24:MI:SS Mon DD, YYYY TZD') now_pst
     , TO_CHAR(systimestamp AT TIME ZONE 'Canada/Eastern', 
                                               'HH24:MI:SS Mon DD, YYYY TZD') now_est 
FROM DUAL

导致:

now_pst                       now_est
09:55:50 Dec 19, 2016 PST     12:55:50 Dec 19, 2016 EST 

现在使用to_timestamp_tz:

SELECT '09:55:50 Dec 19, 2016 PST' now_pst
 , TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 PST', 'HH24:MI:SS Mon DD, YYYY TZD') now_pst_tz
 , '12:55:50 Dec 19, 2016 EST' now_est
 , TO_TIMESTAMP_TZ('12:55:50 Dec 19, 2016 EST', 'HH24:MI:SS Mon DD, YYYY TZD') now_est_tz 
FROM dual

结果:

now_pst                   now_pst_tz                     now_est                   now_est_tz 
09:55:50 Dec 19, 2016 PST 19.12.2016 09:55:50.000 -05:00 12:55:50 Dec 19, 2016 EST 19.12.2016 12:55:50.000 -05:00 

我应该得到的是: NOW_PST_TZ = 19.12.2016 09:55:50.000 -08:00 (不是-05:00)

NOW_EST_TZ = 19.12.2016 12:55:50.000 -05:00

我有很多期望在这里没有发生,但主要是这些应该是同一时间 - 一个在加拿大/东部,一个在加拿大/太平洋。然而,我有两次不同的时间。

to_timestamp_tz无法将字符串转换为正确的TZD。

按要求:

select sessiontimezone, dbtimezone from dual

结果:

SESSIONTIMEZONE DBTIMEZONE 
-05:00          +00:00

2 个答案:

答案 0 :(得分:0)

将格式模型的最后部分从YYYY TZD更改为YYYY TZR TZD - 您在格式模型中缺少TZR

SQL> SELECT '09:55:50 Dec 19, 2016 PST' now_pst
  2   , TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 PST', 'HH24:MI:SS Mon DD, YYYY TZR TZD') now_pst_tz
  3   , '12:55:50 Dec 19, 2016 EST' now_est
  4   , TO_TIMESTAMP_TZ('12:55:50 Dec 19, 2016 EST', 'HH24:MI:SS Mon DD, YYYY TZR TZD') now_est_tz
  5  FROM dual;

NOW_PST                   NOW_PST_TZ
------------------------- ---------------------------------------------------------------------------
NOW_EST                   NOW_EST_TZ
------------------------- ---------------------------------------------------------------------------
09:55:50 Dec 19, 2016 PST 19.12.2016 09:55:50.000 -08:00
12:55:50 Dec 19, 2016 EST 19.12.2016 12:55:50.000 -05:00


1 row selected.

修改:此外,正如Wernfried在答案中所示,最好使用Canada/Pacific而不是PSTCanada/Eastern而不是EST在输入字符串中。

答案 1 :(得分:0)

TZD表示夏令时信息。 TZD值是带有夏令时信息的缩写时区字符串。它必须与TZR中指定的区域相对应。

使用没有时区区域的TZD是不明确的,请查看此查询:

SELECT tzabbrev, tzname, TZ_OFFSET(tzname) 
FROM V$TIMEZONE_NAMES 
WHERE tzabbrev in ('PST', 'EST');

TZABBREV    TZNAME  TZ_OFFSET(TZNAME)
EST America/Antigua -04:00
EST America/Atikokan    -05:00
EST America/Cambridge_Bay   -07:00
EST America/Cancun  -06:00
EST America/Cayman  -05:00
EST America/Chicago -06:00
EST America/Coral_Harbour   -05:00
EST America/Detroit -05:00
EST America/Fort_Wayne  -05:00
EST America/Grand_Turk  -05:00
EST America/Indiana/Indianapolis    -05:00
EST America/Indiana/Knox    -06:00
EST America/Indiana/Marengo -05:00
EST America/Indiana/Petersburg  -05:00
EST America/Indiana/Tell_City   -06:00
EST America/Indiana/Vevay   -05:00
EST America/Indiana/Vincennes   -05:00
EST America/Indiana/Winamac -05:00
EST America/Indianapolis    -05:00
EST America/Iqaluit -05:00
EST America/Jamaica -05:00
EST America/Kentucky/Louisville -05:00
EST America/Kentucky/Monticello -05:00
EST America/Knox_IN -06:00
EST America/Louisville  -05:00
EST America/Managua -06:00
EST America/Menominee   -06:00
EST America/Merida  -06:00
EST America/Moncton -04:00
EST America/Montreal    -05:00
EST America/Nassau  -05:00
EST America/New_York    -05:00
EST America/Nipigon -05:00
EST America/Panama  -05:00
EST America/Pangnirtung -05:00
EST America/Port-au-Prince  -05:00
EST America/Rankin_Inlet    -06:00
EST America/Resolute    -06:00
EST America/Santo_Domingo   -04:00
EST America/Thunder_Bay -05:00
EST America/Toronto -05:00
EST Antarctica/Macquarie    +11:00
EST Australia/ACT   +11:00
EST Australia/Brisbane  +10:00
EST Australia/Broken_Hill   +10:30
EST Australia/Canberra  +11:00
EST Australia/Currie    +11:00
EST Australia/Hobart    +11:00
EST Australia/LHI   +11:00
EST Australia/Lindeman  +10:00
EST Australia/Lord_Howe +11:00
EST Australia/Melbourne +11:00
EST Australia/NSW   +11:00
EST Australia/Queensland    +10:00
EST Australia/Sydney    +11:00
EST Australia/Tasmania  +11:00
EST Australia/Victoria  +11:00
EST Australia/Yancowinna    +10:30
EST CST -06:00
EST Canada/Eastern  -05:00
EST EST -05:00
EST EST5EDT -05:00
EST Jamaica -05:00
EST US/Central  -06:00
EST US/East-Indiana -05:00
EST US/Eastern  -05:00
EST US/Indiana-Starke   -06:00
EST US/Michigan -05:00
PST America/Bahia_Banderas  -06:00
PST America/Boise   -07:00
PST America/Creston -07:00
PST America/Dawson  -08:00
PST America/Dawson_Creek    -07:00
PST America/Ensenada    -08:00
PST America/Hermosillo  -07:00
PST America/Inuvik  -07:00
PST America/Juneau  -09:00
PST America/Los_Angeles -08:00
PST America/Mazatlan    -07:00
PST America/Metlakatla  -08:00
PST America/Santa_Isabel    -08:00
PST America/Sitka   -09:00
PST America/Tijuana -08:00
PST America/Vancouver   -08:00
PST America/Whitehorse  -08:00
PST Canada/Pacific  -08:00
PST Canada/Yukon    -08:00
PST Mexico/BajaNorte    -08:00
PST Mexico/BajaSur  -07:00
PST PST -08:00
PST PST8PDT -08:00
PST Pacific/Pitcairn    -08:00
PST US/Pacific  -08:00
PST US/Pacific-New  -08:00

当您使用TO_TIMESTAMP_TZ()时,您应该使用具有完整区域名称的TZR

您的表达式TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 PST', 'HH24:MI:SS Mon DD, YYYY TZD')相当于TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 '||SESSIONTIMEZONE||' PST', 'HH24:MI:SS Mon DD, YYYY TZR TZD')。如果您当前的会话时区缩写不在PST / EST中,则会失败。