DB2 timestampdiff函数返回意外结果

时间:2011-10-06 16:32:59

标签: datetime timestamp db2 epoch datetime-conversion

我正在使用以下语法

TIMESTAMPDIFF(2, CHAR(CREATED - TIMESTAMP('1970-01-01 00:00:00'))

其中CREATED的类型为TIMESTAMP,数据库为DB2。内涵是将时间戳从epoch转换为millis。如果有更好的功能会更有帮助。

样本数据:
2011-10-04 13:54:50返回的值为1316613290,但实际值应为1317732890(来自http://www.epochconverter.com

查询运行

SELECT TIMESTAMPDIFF(2, CHAR(TIMESTAMP('2011-10-04 13:54:50') - TIMESTAMP('1970-01-01 00:00:00'))) FROM  SYSIBM.SYSDUMMY1;

3 个答案:

答案 0 :(得分:7)

这是因为TIMESTAMPDIFF按预期返回时间戳之间差异的估计,而不是实际值。

来自reference,第435页(假设为iSeries):

  

转换元素值时使用以下假设   到请求的间隔类型:

     
      
  • 一年有365天。
  •   
  • 一年有52周。
  •   
  • 一年有12个月。
  •   
  • 四分之一有3个月。
  •   
  • 一个月有30天。
  •   
  • 一周有7天。
  •   
  • 一天有24小时。
  •   
  • 一小时有60分钟。
  •   
  • 一分钟有60秒。
  •   
  • 一秒钟有1000000微秒。
  •   

使用的实际计算是:

  

秒+(分钟+(小时+((天+(月* 30)+(年* 365))* 24))* 60)* 60

由于显而易见的原因,这是不准确的。没用。

这似乎是返回时间戳算术结果的直接结果 那是;

SELECT                                                              
TIMESTAMP('1971-03-02 00:00:00') - TIMESTAMP('1970-01-01 00:00:00') 
FROM sysibm/sysdummy1        

返回:

10,201,000,000.000000         

Which can be divided into:
  • 1
  • 02个月
  • 01
  • 00小时
  • 00分钟
  • 00
  • 000000微秒

不精确期间/持续时间信息。虽然在很多情况下此类数据 有用,但这不是其中之一。

简短回答:确切的答案无法在数据库中正确计算,实际上不应


答案很长:

计算可能,但相当复杂,绝对不适合数据库内计算。我不打算在这里重现它们(如果你感兴趣,请查看JodaTime,特别是各种Chronology子类)。你最大的问题是几个月的长度不一样。此外,如果您的时间戳不是UTC,那么您将遇到重大问题 - 更具体地说,夏令时会对计算造成严重破坏。为什么?因为任何国家的抵消都可以随时改变。

也许你可以解释为什么你需要毫秒数?希望您使用的是Java(或能够使用Java),并且可以使用java.time。但如果你在iSeries上,它可能是RPG ......

答案 1 :(得分:1)

根据the v9.7 info center,TIMESTAMPDIFF根据一年365天(不是真实的~25%的时间),一个月内30天(不是30天)返回估计的时差真的有75%的时间,虽然平均有点好一点),一天24小时(一些时区的一年中的几天都不是真的),一小时60分钟(万岁,一个正确!),以及一分钟60秒(真正> 99.9%的时间 - 我们确实获得闰秒)。

所以,不,这不是在DB2中获取纪元时间的方法。到目前为止,我已经把时间作为时间戳,并在客户端转换它。

答案 2 :(得分:1)

部分错误的发生是因为TIMESTAMPDIFF函数的不准确性,正如其他人指出的那样。

另一个错误来源是因为Epoch基于GMT - 因此您必须考虑当地时区。

因此,您可以使用以下表达式执行此操作:

(DAYS(timestamp('2011-10-04-13.54.50.000000') - current timezone) - DAYS('1970-01-01-00.00.00.000000')) * 86400 + MIDNIGHT_SECONDS(timestamp('2011-10-04-13.54.50.000000') - current timezone)

您可以编写一个简单的UDF来简化此操作:

create or replace function epoch (in db2ts timestamp)
   returns bigint
   language sql
   deterministic
   no external action
   return (days(db2ts - current timezone) - days('1970-01-01-00.00.00.000000')) * 86400 + midnight_seconds(db2ts - current timezone);
祝你好运,