Why does Oracle's to_timestamp_tz return the wrong time and/or time zone?

≡放荡痞女 提交于 2019-12-25 16:46:31

问题


I've worked with Oracle's timestamp with time zone before, but this time I'm getting values as strings and trying to load them to the database.

When converting the string, I end up with a value in the database time zone. This is odd, but workable if it adjusted the time accordingly yet it doesn't. See below:

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

which results in:

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

now to use 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

the result:

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 

what I should get is: NOW_PST_TZ = 19.12.2016 09:55:50.000 -08:00 (not -05:00)

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

I have a lot of expectations that aren't happening here, but mainly that these are supposed to be the same time - one in Canada/Eastern and one in Canada/Pacific. Yet I'm getting 2 different times.

to_timestamp_tz is failing to convert the string to the correct TZD.

as requested:

select sessiontimezone, dbtimezone from dual

result:

SESSIONTIMEZONE DBTIMEZONE 
-05:00          +00:00

回答1:


Change the final part of the format model from YYYY TZD to YYYY TZR TZD - you are missing TZR in the format model.

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.

Edit: Moreover, as Wernfried shows in his answer, it is better to use Canada/Pacific rather than PST and Canada/Eastern rather than EST in the input string.




回答2:


TZD means Daylight saving information. The TZD value is an abbreviated time zone string with daylight saving information. It must correspond with the region specified in TZR.

Using TZD without time zone region is ambiguous, check with this query:

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

When you use TO_TIMESTAMP_TZ() then you should use TZR with full region name.

Your expression TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 PST', 'HH24:MI:SS Mon DD, YYYY TZD') is equivalent to TO_TIMESTAMP_TZ('09:55:50 Dec 19, 2016 '||SESSIONTIMEZONE||' PST', 'HH24:MI:SS Mon DD, YYYY TZR TZD'). It will fail if your current session time zone abbreviation is not in PST/EST.



来源:https://stackoverflow.com/questions/41228576/why-does-oracles-to-timestamp-tz-return-the-wrong-time-and-or-time-zone

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!