【问题标题】:Cast timestamp to timestamp with time zone将时间戳转换为带有时区的时间戳
【发布时间】:2015-01-05 18:02:33
【问题描述】:

我正在尝试将时间戳转换为带有时区的时间戳,并添加 GMT 时区:

to_timestamp(to_char(t.time_started, 'DD-MON-YYYY hh24:mi:ss')
  || nvl2(t.time_started, ' GMT', null), ('DD-MON-YYYY hh24:mi:ss tzd'))

但这会导致 ORA-01812 日期格式无法识别。如何指定添加时区?

【问题讨论】:

    标签: oracle oracle11g


    【解决方案1】:

    您需要使用the to_timestamp_tz() function,而不仅仅是to_timestamp; 'tzd' 格式元素无法识别,因此您的错误:

    select to_timestamp_tz(to_char(t.time_started, 'DD-MON-YYYY hh24:mi:ss')
      || nvl2(t.time_started, ' GMT', null), ('DD-MON-YYYY hh24:mi:ss tzd'))
    from t;
    
    TO_TIMESTAMP_TZ(TO_CHAR(T.TIME_STARTED,'DD-MON-YYYYHH24:MI:SS')||NVL2(T.TIME_STARTED,'GMT',NULL),('DD-MON-YYYYHH24:MI:SSTZD'))
    ------------------------------------------------------------------------------------------------------------------------------
    05-JAN-15 18.09.28.000000000 EUROPE/LONDON                                                                                     
    

    您会注意到,您选择的格式模型会丢失小数秒。

    您还可以使用the at time zone expression 指定一个值所代表的时区:

    select t.time_started at time zone 'GMT' from t;
    
    T.TIME_STARTEDATTIMEZONE'GMT'     
    -----------------------------------
    05-JAN-15 18.12.53.419495000 GMT    
    

    或者您可以使用cast,正如您的问题标题所建议的那样,我相信这是假设系统时区:

    select cast(t.time_started as timestamp with time zone) from t;
    
    CAST(T.TIME_STARTEDASTIMESTAMPWITHTIMEZONE)
    -------------------------------------------
    05-JAN-15 18.14.19.236338000 EUROPE/LONDON  
    

    我在英国,所以这对我有用,但如果您的服务器位于不同的时区,您可能需要对其进行转换。

    【讨论】:

    • 除非有非常特殊的需求,否则使用AT TIME ZONE 子句绝对是这里的方法
    • 同意;仅涵盖来自 OP 的原始查询和标题的基础。看来我应该更多地强调at time zone 选项。
    【解决方案2】:

    如果t.time_started 列的类型为TIMESTAMP,并且请求是在给定时区中解释此时间戳,则此处将使用函数FROM_TZ

    相比之下,AT TIME ZONE 子句用于将TIMESTAMP WITH TIME ZONE 值从一个时区移动到另一个时区。

    这意味着使用以下SELECT 语句首先将TIMESTAMP 值隐式转换(使用当前会话时区)到TIMESTAMP WITH TIME ZONE 值,然后在另一个时区显示该值,这可能不是预期的结果和问题的解决方案。

    select t.time_started at time zone 'GMT' from t
    

    请参阅以下示例,其中显示了差异。 (我的会话时区目前是 +2:00)。

    CREATE TABLE t
    (
       time_started    TIMESTAMP
    );
    
    INSERT INTO t
         VALUES (CURRENT_TIMESTAMP);
    
    SELECT * FROM t;
    
    
    SELECT FROM_TZ(t.time_started, 'GMT') as T1, t.time_started AT TIME ZONE 'GMT' as T2 FROM t
    

    结果是:

    +-----------------------------------+-----------------------------------+
    |                T1                 |                T2                 |
    +-----------------------------------+-----------------------------------+
    | 2019-07-16 12:17:29,068660 +00:00 | 2019-07-16 10:17:29,068660 +00:00 |
    +-----------------------------------+-----------------------------------+
    

    两个值都以 GMT 显示,但明显不同。

    【讨论】:

      猜你喜欢
      • 2018-12-18
      • 2021-09-22
      • 2019-10-07
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 2020-11-27
      • 1970-01-01
      相关资源
      最近更新 更多