【问题标题】:Convert CST to UTC at the time of the Daylight Savings start and end in Oracle Sql在 Oracle Sql 中夏令时开始和结束时将 CST 转换为 UTC
【发布时间】:2020-10-25 11:45:26
【问题描述】:

我正在尝试在 Oracle SQL 中将时间戳从本地时区(美国/芝加哥,即 CST)转换为 UTC。我尝试了几个 SQL 语句:

SELECT CAST('08-MAR-2020 02.05.02.575000000 AM' AS TIMESTAMP WITH TIME ZONE ) AT TIME ZONE 'UTC' FROM dual;

从双重选择 SYS_EXTRACT_UTC(CAST('08-MAR-2020 02.05.02.575000000 AM' AS TIMESTAMP));

select from_tz(CAST ('08-MAR-2020 02.05.02.575000000 AM' AS TIMESTAMP),'CST') at TIME ZONE 'UTC' with_daylight_savings from dual;

SELECT TO_TIMESTAMP('08-MAR-15 02.05.02.575000000 AM') AT TIME ZONE 'UTC' FROM dual;

但是,我收到所有这些语句的相同错误消息。

ORA-01878:在日期时间或间隔中找不到指定的字段。

01878。 00000 - “在日期时间或间隔中找不到指定的字段”

*原因:在日期时间或间隔中找不到指定的字段。

*操作:确保指定的字段在日期时间或间隔内。

它可以很好地转换所有其他时间,除了夏令时的开始和结束时间在凌晨 2 点到 3 点之间。如果我更改为 01:00 AM 或 03:00 AM,它会很好地转换时间戳。

我尝试了几种解决方案,但似乎都不适合我。

首先我尝试用 TZR 元素添加 TZD 元素。

SELECT TO_TIMESTAMP_TZ('08-MAR-2020 02.05.02.575000000 America/Chicago CDT', 'DD-MON-YYYY HH.MI.SS.FF9 TZR TZD', 'NLS_DATE_LANGUAGE = 美国') 在时区 'UTC'从双;

但是,运行此语句,它给了我 ORA-01857: not a valid time zone。如果我使用 CST 运行相同的语句,我会得到 ORA-01878: specified field not found in datetime or interval。

我的问题是这个。我在 oracle 中有一个表,其中有一个带有 TIMESTAMP(没有 TIMEZONE 信息)的字段,如下所示:'08-MAR-2020 02.05.02.575000000 AM'。我正在考虑将时区设置为 'America/Chicago'。我的目标是将字符串作为输出格式以 'YYYY-MM-DD"T"HH24:MI:SS.FF"Z"' 转换为 UTC 时间。

如果有人碰到它并能够解决它,请分享。谢谢。

【问题讨论】:

  • 嗨。您是否在所有查询中都收到错误?我的意思是,我只对第三个有问题,我想我知道为什么。但其他人对我来说工作正常。你能在你的 sqlplus 中重现错误吗?
  • 其他为您工作,因为您的 SYSTEMTIMESTAMP 可能是没有歧义的那个。正如答案所说,CST 有不同的 TZ_OFFSET。这就是为什么他们为我呈现错误,为你呈现错误。

标签: oracle datetime


【解决方案1】:

'08-MAR-2020 02.05.02.575000000 AM' 不是TIMESTAMP 值,它是一个字符串

当您想将字符串转换为 TIMESTAMP 时,您应该始终包含以下格式:

TO_TIMESTAMP('08-MAR-2020 02.05.02.575000000 AM', 'DD-MON-YYYY HH.MI.SS.FF9', 'NLS_DATE_LANGUAGE = american')

如果你想创建一个TIMESTAMP WITH TIME ZONE,那么你应该使用

TO_TIMESTAMP_TZ('08-MAR-2020 02.05.02.575000000 AM ???', 'DD-MON-YYYY HH.MI.SS.FF9 TZR', 'NLS_DATE_LANGUAGE = american')

我不知道CST是什么意思,很模棱两可:

SELECT tzabbrev, tzname, TZ_OFFSET(tzname) 
FROM V$TIMEZONE_NAMES tz 
where tzabbrev = 'CST'

+--------------------------------------------------------------------------------+
|TZABBREV                       |TZNAME                        |TZ_OFFSET(TZNAME)|
+--------------------------------------------------------------------------------+
|CST                            |America/Atikokan              |-05:00           |
|CST                            |America/Bahia_Banderas        |-05:00           |
|CST                            |America/Belize                |-06:00           |
|CST                            |America/Cambridge_Bay         |-06:00           |
|CST                            |America/Cancun                |-05:00           |
|CST                            |America/Chicago               |-05:00           |
|CST                            |America/Chihuahua             |-06:00           |
|CST                            |America/Coral_Harbour         |-05:00           |
|CST                            |America/Costa_Rica            |-06:00           |
|CST                            |America/Detroit               |-04:00           |
|CST                            |America/El_Salvador           |-06:00           |
|CST                            |America/Fort_Wayne            |-04:00           |
|CST                            |America/Guatemala             |-06:00           |
|CST                            |America/Havana                |-04:00           |
|CST                            |America/Hermosillo            |-07:00           |
|CST                            |America/Indiana/Indianapolis  |-04:00           |
|CST                            |America/Indiana/Knox          |-05:00           |
|CST                            |America/Indiana/Marengo       |-04:00           |
|CST                            |America/Indiana/Petersburg    |-04:00           |
|CST                            |America/Indiana/Tell_City     |-05:00           |
|CST                            |America/Indiana/Vevay         |-04:00           |
|CST                            |America/Indiana/Vincennes     |-04:00           |
|CST                            |America/Indiana/Winamac       |-04:00           |
|CST                            |America/Indianapolis          |-04:00           |
|CST                            |America/Iqaluit               |-04:00           |
|CST                            |America/Kentucky/Louisville   |-04:00           |
|CST                            |America/Kentucky/Monticello   |-04:00           |
|CST                            |America/Knox_IN               |-05:00           |
|CST                            |America/Louisville            |-04:00           |
|CST                            |America/Managua               |-06:00           |
|CST                            |America/Matamoros             |-05:00           |
|CST                            |America/Mazatlan              |-06:00           |
|CST                            |America/Menominee             |-05:00           |
|CST                            |America/Merida                |-05:00           |
|CST                            |America/Mexico_City           |-05:00           |
|CST                            |America/Monterrey             |-05:00           |
|CST                            |America/North_Dakota/Beulah   |-05:00           |
|CST                            |America/North_Dakota/Center   |-05:00           |
|CST                            |America/North_Dakota/New_Salem|-05:00           |
|CST                            |America/Ojinaga               |-06:00           |
|CST                            |America/Pangnirtung           |-04:00           |
|CST                            |America/Rainy_River           |-05:00           |
|CST                            |America/Rankin_Inlet          |-05:00           |
|CST                            |America/Regina                |-06:00           |
|CST                            |America/Resolute              |-05:00           |
|CST                            |America/Swift_Current         |-06:00           |
|CST                            |America/Tegucigalpa           |-06:00           |
|CST                            |America/Thunder_Bay           |-04:00           |
|CST                            |America/Winnipeg              |-05:00           |
|CST                            |Asia/Chongqing                |+08:00           |
+--------------------------------------------------------------------------------+

一旦您有了 UTC,您就可以转换为 UTC:

SYS_EXTRACT_UTC(TO_TIMESTAMP_TZ('08-MAR-2020 02.05.02.575000000 AM ???', 'DD-MON-YYYY HH.MI.SS.FF9 TZR', 'NLS_DATE_LANGUAGE = american'))

TO_TIMESTAMP_TZ('08-MAR-2020 02.05.02.575000000 AM ???', 'DD-MON-YYYY HH.MI.SS.FF9 TZR', 'NLS_DATE_LANGUAGE = american') AT TIME ZONE UTC

如果时间不明确,即夏令时的转换,那么您也可以指定它(使用 TIMESTAMP 文字,因为它更短):

TIMESTAMP '2020-03-08 02.05.02.575 America/Los_Angeles PDT'

TIMESTAMP WITH TIME ZONE Data Type

消除时间切换时边界情况的歧义 从标准时间到夏令时,同时使用 TZR 格式 元素和相应的 TZD 格式元素。 TZD 格式 element 是带Daylight的时区区域的缩写 包括节省时间信息。例如美国太平洋地区的 PST 美国太平洋夏令时间的标准时间和 PDT。下列 规范确保返回夏令时值:

TIMESTAMP '1999-10-29 01:30:00 America/Los_Angeles PDT'

如果不添加 TZD 格式元素,则 datetime 值为 模棱两可,然后 Oracle 数据库返回一个错误,如果你有 ERROR_ON_OVERLAP_TIME 会话参数设置为 TRUE。如果 ERROR_ON_OVERLAP_TIME 设置为 FALSE(默认值),然后 Oracle 数据库将不明确的日期时间解释为标准时间。

【讨论】:

  • 非常感谢您的回答。在此日期之前,我不知道 CST 有不同的时区偏移量。我已将我的问题更新为比 CST 更准确
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 2014-06-01
  • 2014-08-13
  • 2021-11-04
  • 1970-01-01
  • 2010-09-22
相关资源
最近更新 更多