'15-JAN-17 05.00.00.000000000 AM' 是一个字符串,而不是时间戳。您可以按照@D-Shih 的建议将其转换为时间戳(没有时区),但您应该指定格式掩码和日期语言,而不是依赖 NLS 设置:
AND HR = to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24);
或者如果它是一个固定值(可能不是,或者你可以改变那个文字):
AND HR = timestamp '2017-01-15 05:00:00' - (1/24);
从时间戳中减去天数会给你一个日期结果,所以你可能真的想这样做:
AND HR = timestamp '2017-01-15 05:00:00' - interval '1' hour;
这现在保留为时间戳,但您没有时区信息。如果您知道时区,则可以将其包含在字符串文字和格式掩码中,或包含在时间戳文字中,例如:
AND HR = timestamp '2017-01-15 05:00:00 America/Los_Angeles' - (1/24);
或者来自您的原始字符串,如果您只需要使用这些,您可以使用from_tz():
AND HR = from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour;
最后做间隔减法应该意味着它正确处理了夏令时。
各种转换的演示,从您的字符串值开始:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF1';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF1 TZR TZD';
select
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') as a_timestamp,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24) as b_date,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - interval '1' hour as c_timestamp,
from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour as d_timestamp_tz
from dual;
A_TIMESTAMP B_DATE C_TIMESTAMP D_TIMESTAMP_TZ
--------------------- ------------------- --------------------- ---------------------------------------------
2017-01-15 05:00:00.0 2017-01-15 04:00:00 2017-01-15 04:00:00.0 2017-01-15 04:00:00.0 AMERICA/LOS_ANGELES PST