ORA-01870 试图将日期转换为带有时区的时间戳

Posted

技术标签:

【中文标题】ORA-01870 试图将日期转换为带有时区的时间戳【英文标题】:ORA-01870 trying to convert from date into timestamp with time zone 【发布时间】:2021-10-04 07:44:54 【问题描述】:

在 Oracle DB 11g 上使用 SQL DEVELOPER 运行以下 PL/SQL 匿名块时

SET SERVEROUTPUT ON;

DECLARE
    d_next_run_date TIMESTAMP WITH TIME ZONE;
BEGIN
    dbms_scheduler.evaluate_calendar_string(
            calendar_string => 'FREQ=DAILY;INTERVAL=15', 
            start_date => TO_TIMESTAMP_TZ('04/06/2021', 'DD/MM/YYYY'),
            return_date_after => TO_TIMESTAMP_TZ('01/01/2022', 'DD/MM/YYYY'),
            next_run_date => d_next_run_date
            );

    dbms_output.put_line(d_next_run_date);
END;

抛出以下异常

ORA-01870: the intervals or datetimes are not mutually comparable
ORA-06512: at "SYS.DBMS_SCHEDULER", line 3599
ORA-06512: at line 4
01870. 00000 -  "the intervals or datetimes are not mutually comparable"
*Cause:    The intervals or datetimes are not mutually comparable.
*Action:   Specify a pair of intervals or datetimes that are mutually
           comparable.

我怀疑这个问题与时区有关。

如果将参数更改为以下,则不会引发异常(注意我更改了传递给参数return_date_after的值)

SET SERVEROUTPUT ON;

DECLARE
    d_next_run_date TIMESTAMP WITH TIME ZONE;
BEGIN
    dbms_scheduler.evaluate_calendar_string(
            calendar_string => 'FREQ=DAILY;INTERVAL=15', 
            start_date => TO_TIMESTAMP_TZ('04/06/2021', 'DD/MM/YYYY'),
            return_date_after => TO_TIMESTAMP_TZ('01/01/2021', 'DD/MM/YYYY'),
            next_run_date => d_next_run_date
            );

    dbms_output.put_line(d_next_run_date);
END;

或者如果参数更改为以下(我再次更改了传递给参数 return_date_after 的值)

SET SERVEROUTPUT ON;

DECLARE
    d_next_run_date TIMESTAMP WITH TIME ZONE;
BEGIN
    dbms_scheduler.evaluate_calendar_string(
            calendar_string => 'FREQ=DAILY;INTERVAL=15', 
            start_date => TO_TIMESTAMP_TZ('04/06/2021', 'DD/MM/YYYY'),
            return_date_after => TO_TIMESTAMP_TZ('01/06/2022', 'DD/MM/YYYY'),
            next_run_date => d_next_run_date
            );

    dbms_output.put_line(d_next_run_date);
END;

我必须满足的要求不需要支持时区。如果可能,我想将数据类型 DATE 与过程 dbms_scheduler.evaluate_calendar_string 一起使用。但是,dbms_scheduler.evaluate_calendar_string 参数的类型为 TIMESTAMP WITH TIMEZONE。如何从 DATE 转换为 TIMESTAMP WITH TIMEZONE 并避免该异常?

我注意到当一个对应于夏季的日期值被传递到参数 return_date_after 时会引发异常。所以这个错误可能与夏令时有关。

数据库版本:11.2.0.1.0

nls 参数

【问题讨论】:

您的会话在哪个时区 (select sessiontimezone from dual); select TO_TIMESTAMP_TZ('01/01/2022', 'DD/MM/YYYY') from dual 返回什么? 试试演员表。 `select cast (sysdate as timestamp with time zone) from dual;' 你真的喜欢半年后入职吗? 您使用的是哪个 Oracle 版本?我的是 12.2.0.1,在我的系统上你的代码运行得很好;没有抛出错误,程序正确打印下一次运行日期。 但是,我看到你的两个版本(原始代码和你说的那个有效)是相同的。您在发布此内容时是否犯了错误 - 也许您引发错误的代码不是您发布为“现有代码”的代码? 【参考方案1】:

我设法通过在将字符转换为 TIMESTAMP WITH TIMEZONE 时添加时间和时区来避免该错误

SET SERVEROUTPUT ON;

DECLARE
    d_next_run_date TIMESTAMP WITH TIME ZONE;
BEGIN
    dbms_scheduler.evaluate_calendar_string(
            calendar_string => 'FREQ=DAILY;INTERVAL=15', 
            start_date => TO_TIMESTAMP_TZ('04/06/2021 00:00:00 00:00', 'DD/MM/YYYY HH24:MI:SS TZH:TZM'),
            return_date_after => TO_TIMESTAMP_TZ('01/01/2022 00:00:00 00:00', 'DD/MM/YYYY HH24:MI:SS TZH:TZM'),
            next_run_date => d_next_run_date
            );

    dbms_output.put_line(d_next_run_date);
END;
/

输出

15/01/22 00:00:00,000000 +00:00

【讨论】:

以上是关于ORA-01870 试图将日期转换为带有时区的时间戳的主要内容,如果未能解决你的问题,请参考以下文章

将纪元时间戳列转换为带有时区的日期时间

试图在 Panda DataFrame 中将感知本地日期时间转换为天真的本地日期时间

如何将熊猫中的日期时间列全部转换为同一时区

带有时区的 PostgreSQL date()

JSON如何反序列化日期时间并将UTC转换为指定时区?

Python pytz 时区转换返回的值与不同日期的时区偏移量不同