Datetime 返回意外结果的DB2 timestampdiff函数

Datetime 返回意外结果的DB2 timestampdiff函数,datetime,timestamp,db2,epoch,datetime-conversion,Datetime,Timestamp,Db2,Epoch,Datetime Conversion,我使用以下语法 TIMESTAMPDIFF(2, CHAR(CREATED - TIMESTAMP('1970-01-01 00:00:00')) 其中,CREATED的类型为TIMESTAMP,数据库为DB2。其目的是将时间戳从历元转换为毫秒。如果有更好的功能,那将更有帮助 样本数据: 对于2011-10-04 13:54:50返回值为1316613290,但实际值应为1317732890(从中获取) 要运行的查询 SELECT TIMESTAMPDIFF(2, CHAR(TIMESTAMP

我使用以下语法

TIMESTAMPDIFF(2, CHAR(CREATED - TIMESTAMP('1970-01-01 00:00:00'))
其中,
CREATED
的类型为
TIMESTAMP
,数据库为DB2。其目的是将时间戳从历元转换为毫秒。如果有更好的功能,那将更有帮助

样本数据:
对于
2011-10-04 13:54:50
返回值为
1316613290
,但实际值应为
1317732890
(从中获取)

要运行的查询

SELECT TIMESTAMPDIFF(2, CHAR(TIMESTAMP('2011-10-04 13:54:50') - TIMESTAMP('1970-01-01 00:00:00'))) FROM  SYSIBM.SYSDUMMY1;
根据,TIMESTAMPDIFF返回一个估计的时差,基于一年365天(不正确~25%的时间)、一个月30天(不正确75%的时间,尽管平均值略好于此)、一天24小时(在某些时区一年中的几天不正确)、一小时60分钟(万岁,没错!),一分钟60秒(准确率>99.9%——我们得到的是闰秒)


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

这是由于
TIMESTAMPDIFF
返回时间戳之间差异的估计值,而不是预期的实际值

从第435页(假定为iSeries):

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

  • 一年有365天
  • 一年有52周
  • 一年有12个月
  • 一个季度有三个月
  • 一个月有30天
  • 一周有7天
  • 一天有24小时
  • 一小时有60分钟
  • 一分钟有60秒
  • 一秒钟有1000000微秒
而实际使用的计算是:

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

这显然是不准确的。没有帮助

这似乎是时间戳算术结果返回方式的直接结果。
就是,

返回:

10,201,000,000.000000         

Which can be divided into:
  • 1
    年份
  • 02
    月份
  • 01
  • 00
    小时
  • 00
    分钟
  • 00
  • 000000
    微秒
这是不精确的期间/持续时间信息。虽然这种类型的数据在很多情况下都很有用,但这不是其中之一

简短回答:准确答案无法在数据库中正确计算,事实上不应如此


长答覆:

这些计算是可能的,但相当复杂,而且绝对不适合数据库内计算。我不打算在这里复制它们(如果您感兴趣,请查阅,特别是各种
年表
子类)。你最大的问题是,月份的长度不尽相同。此外,如果时间戳不是UTC,您将遇到重大问题-更具体地说,夏令时将对计算造成严重破坏。为什么?因为对于任何国家,补偿都可以随时改变


也许你可以解释一下为什么需要毫秒数?希望您正在使用Java(或者能够这样做),并且可以使用
Java.time
。但如果您使用的是iSeries,则可能是RPG…

正如其他人所指出的,部分错误是由于TIMESTAMPDIFF函数的不准确造成的

发生错误的另一个原因是历元基于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);
祝你好运

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);