2016-12-05 69 views
0

我有简单的计算,我从日期减去间隔用时:与格式甲骨文TO_DATE不显示时间

select TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - to_dsinterval('00 0:05:00') from dual; 

它工作正常,结果:2016年12月5日22点59分59秒

但它无法与时区正确工作,所以下一种方法解决了时区问题。我只是包装用TO_DATE()一次

select TO_DATE(
TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - to_dsinterval('00 0:05:00')) from dual; 

表达,但现在事实证明时间为零。结果应该是:2016年12月5日22时59分五十九秒但实际:2016年12月5日00:00:00

如果我添加格式外TO_DATE就象这样:

select to_date(TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - to_dsinterval('00 0:05:00'), 'YYYY-MM-DD HH24:MI:SS') from dual; 

结果变得很奇怪:0005-12-16 00:00:00 我在做什么错了?

+1

减法的结果已经是日期。你不需要另一个'to_date()',这不能解决时区问题。如果你想在时区上进行一些操作,请使用'时区时间戳' – Kacper

回答

0

TO_DATE(char, fmt, nls)需要VARCHAR2参数。

执行TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - to_dsinterval('00 0:05:00')返回DATE的数据类型,当你把它传递给TO_DATE()甲骨文将其转换为VARCHAR2数据类型,因此参数的预期数据类型匹配(隐式调用TO_CHAR(value, NLS_DATE_FORMAT)执行这个转换),然后转化这个回数据类型为DATE

你只需要做:

SELECT TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') 
     - to_dsinterval('00 0:05:00') 
FROM DUAL; 

如果你要处理的时区,然后使用一个TIMESTAMP AT TIME ZONE,只是把它转换到任何时区要存储的日期为:

SELECT TIMESTAMP '2016-12-05 23:04:59 Europe/Paris' AT TIME ZONE 'UTC' 
FROM DUAL; 

(将在巴黎时区创建您的时间戳并将其转换为UTC时区中的正确时间)。

0

DATE数据类型不支持任何时区功能,您必须使用TIMESTAMP WITH TIME ZONE

您的查询

SELECT TO_DATE(TO_DATE('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - TO_DSINTERVAL('00 0:05:00'), 'YYYY-MM-DD HH24:MI:SS') 
FROM dual; 

做以下操作:

  1. 创建DATE '2016年12月5日23时04分59秒'
  2. 减去间隔00○时05分00' 秒
  3. 转换为VARCHAR2(使用NLS_DATE_FORMAT格式)
  4. 转换为使用YYYY-MM-DD HH24:MI:SS格式

如果您NLS_DATE_FORMAT将等于YYYY-MM-DD HH24:MI:SS这个查询返回正确的输出。

使用这一个:

SELECT TO_TIMESTAMP('2016-12-05 23:04:59', 'YYYY-MM-DD HH24:MI:SS') - TO_DSINTERVAL('00 0:05:00') 
FROM dual; 

TO_DATE(...工作为好。如果您需要时区支持,您必须执行以下操作:

SELECT TO_TIMESTAMP_TZ('2016-12-05 23:04:59 Europe/Berlin', 'YYYY-MM-DD HH24:MI:SS TZR') - TO_DSINTERVAL('00 0:05:00') 
FROM dual; 
+0

'DATE'数据类型可以在它们上执行INTERVAL DAY TO SECOND算术。如果你做了'SELECT DUMP(TO_DATE('2016-12-05 23:04:59','YYYY-MM-DD HH24:MI:SS') - TO_DSINTERVAL('00 0:05:00'))FROM DUAL '返回'Typ = 13'这是'DATE'数据类型,所以不会隐式转换为'TIMESTAMP'。 – MT0

+0

你是对的,我纠正了我的答案。 –