以小时和分钟计算两个日期之间的差异

Posted

技术标签:

【中文标题】以小时和分钟计算两个日期之间的差异【英文标题】:Find the difference between two dates in hours and minutes 【发布时间】:2016-02-17 10:43:36 【问题描述】:

我正在尝试想出一种方法来计算两个日期之间的小时和分钟差异。

我有一个包含两列 Start DateTimeStamp 的表格:

Start Date              Timestamp
--------------------    --------------------
05/JAN/2016 05:30:00    01/JAN/2016 10:02:29
30/JAN/2016 06:10:00    18/JAN/2016 19:24:00
23/JAN/2016 06:10:00    08/JAN/2016 10:46:00
05/JAN/2016 05:30:00    30/DEC/2015 16:07:00
23/JAN/2016 06:10:00    08/JAN/2016 12:18:05
01/JAN/2016 14:10:00    16/DEC/2015 16:36:56
01/JAN/2016 14:10:00    16/DEC/2015 11:41:00
03/JAN/2016 05:15:00    02/JAN/2016 11:23:15
03/JAN/2016 05:15:00    02/JAN/2016 07:52:00

我使用查询:

select ROUND(RM_LIVE.CRWGNDACTTIME.GNDACTSTARTRM_LIVE.TRANSACTIONLOG.TIMESTAMP,2)
                       AS "Difference"
  from Transaction;

查询结果为:

0.002721428571428571428571428571428571428571
0.008178571428571428571428571428571428571429
0.0105785714285714285714285714285714285714
0.003971428571428571428571428571428571428571

预期结果:

133:23
 91:28
355:24
353:52
274:46

我使用这个公式在 Excel 中得到了预期的结果:

= MAX(T982+U982,W982+V982) - MIN(T982+U982,W982+V982)

如何在 Oracle SQL 中获得相同的结果?

CASE
  WHEN trunc(24 * abs(RM_LIVE.TRANSACTIONLOG.TIMESTAMP
- RM_LIVE.CRWGNDACTTIME.GNDACTSTART))
  ||':'|| lpad(round(60 * mod(24 * abs(RM_LIVE.TRANSACTIONLOG.TIMESTAMP
- RM_LIVE.CRWGNDACTTIME.GNDACTSTART), 1)), 2, '0')  <= '11:00' THEN     'LESS'
ELSE 'MORE'
END AS "mORE/LESS",


386:29  1055    01-JAN-16   16-DEC-15   MORE
**102:41    1055    08-NOV-15   04-NOV-15   LESS**
381:33  1055    01-JAN-16   16-DEC-15   MORE
176:45  1055    20-NOV-15   12-NOV-15   MORE
**119:54    1055    08-NOV-15   03-NOV-15   LESS** 

【问题讨论】:

我查过了,但没有我要找的只有几天而不是几小时 他的询问结果在 24 小时内,而我询问两个日期的不同时间,所以有两个不同的事情 为什么它们不同?你的第一行05/JAN/2016 05:30:00 01/JAN/2016 10:02:29,相差3天19小时27分30秒; 3 天是 72 小时,所以总共是 91 小时。对该链接问题的查询给出了 91:27:30。对于您的第四个值,它给出 133:22。你可以省略秒部分吗? 但我不知道如何进行查询?? 谢谢 完成回合(24*( to_date(RM_LIVE.CRWGNDACTTIME.GNDACTSTART,'dd/mon/yyyy HH24:MI:SS')-to_date(RM_LIVE.TRANSACTIONLOG.TIMESTAMP,'dd/mon/ yyyy HH24:MI:SS')),2) 作为“差异”, 【参考方案1】:

我在this answer 中展示了一些带有解释的变体,但它似乎比你想要的稍微多一点——你不想看到秒数——并且不允许超过 100 小时。

获得所需输出的最简单方法是:

trunc(24 * (RM_LIVE.CRWGNDACTTIME.GNDACTSTART
    - RM_LIVE.TRANSACTIONLOG.TIMESTAMP))
  ||':'|| lpad(round(60 * mod(24 * (RM_LIVE.CRWGNDACTTIME.GNDACTSTART
    - RM_LIVE.TRANSACTIONLOG.TIMESTAMP), 1)), 2, '0')
as difference

第一部分获取完整小时数,这类似于您在评论中添加的方法,但截断而不是四舍五入以仅获取完整小时数。然后是冒号分隔符。然后通过从小时计算中获取余数来计算分钟 - 通过mod() - 这是小时的小数,并将其乘以 60。lpad() 在分钟数中添加前导零,但你可以请改用to_char()

如果您有混合范围,其中时间戳可能在开始时间之前或之后,那么您可以使用 the abs() function 始终获得肯定的结果。

trunc(24 * abs(RM_LIVE.CRWGNDACTTIME.GNDACTSTART
    - RM_LIVE.TRANSACTIONLOG.TIMESTAMP))
  ||':'|| lpad(round(60 * mod(24 * abs(RM_LIVE.CRWGNDACTTIME.GNDACTSTART
    - RM_LIVE.TRANSACTIONLOG.TIMESTAMP), 1)), 2, '0')
as difference

作为一个演示,将您的数据模拟在一个表中:

create table your_table(id, start_time, timestamp) as
  select 1, to_date ('05/JAN/2016 05:30:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('01/JAN/2016 10:02:29', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 2, to_date ('30/JAN/2016 06:10:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('18/JAN/2016 19:24:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 3, to_date ('23/JAN/2016 06:10:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('08/JAN/2016 10:46:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 4, to_date ('05/JAN/2016 05:30:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('30/DEC/2015 16:07:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 5, to_date ('23/JAN/2016 06:10:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('08/JAN/2016 12:18:05', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 6, to_date ('01/JAN/2016 14:10:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('16/DEC/2015 16:36:56', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 7, to_date ('01/JAN/2016 14:10:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('16/DEC/2015 11:41:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 8, to_date ('03/JAN/2016 05:15:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('02/JAN/2016 11:23:15', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 9, to_date ('03/JAN/2016 05:15:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('02/JAN/2016 07:52:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 10, to_date ('16/JAN/2016 11:15:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('16/JAN/2016 12:44:00', 'DD/MON/YYYY HH24:MI:SS') from dual
  union all select 11, to_date ('16/JAN/2016 11:15:00', 'DD/MON/YYYY HH24:MI:SS'), to_date('16/JAN/2016 12:50:00', 'DD/MON/YYYY HH24:MI:SS') from dual;

等效查询:

select start_time, timestamp, trunc(24 * abs(start_time - timestamp))
    ||':'|| lpad(round(60 * mod(24 * abs(start_time - timestamp), 1)), 2, '0')
    as difference
from your_table
order by id;

START_TIME          TIMESTAMP           DIFFERENCE
------------------- ------------------- ----------
2016-01-05 05:30:00 2016-01-01 10:02:29 91:28     
2016-01-30 06:10:00 2016-01-18 19:24:00 274:46    
2016-01-23 06:10:00 2016-01-08 10:46:00 355:24    
2016-01-05 05:30:00 2015-12-30 16:07:00 133:23    
2016-01-23 06:10:00 2016-01-08 12:18:05 353:52    
2016-01-01 14:10:00 2015-12-16 16:36:56 381:33    
2016-01-01 14:10:00 2015-12-16 11:41:00 386:29    
2016-01-03 05:15:00 2016-01-02 11:23:15 17:52     
2016-01-03 05:15:00 2016-01-02 07:52:00 21:23     
2016-01-16 11:15:00 2016-01-16 12:44:00 1:29      
2016-01-16 11:15:00 2016-01-16 12:50:00 1:35      

你不能轻易地比较你想要的字符串值——它必须是一个像91:28这样的值的字符串——因为数字的字符串比较不能很好地工作。如您所见,比较“119:54”和“11:00”实际上是比较每个字符串的第三个字符,因为前两个字符相同,所以9:

将其保留为小数进行比较会更简单:

CASE
  WHEN round(24 * abs(RM_LIVE.TRANSACTIONLOG.TIMESTAMP
    - RM_LIVE.CRWGNDACTTIME.GNDACTSTART), 2) <= 11 THEN 'LESS"
ELSE 'MORE'
END AS "mORE/LESS",

对于 91:28 示例,它将比较小数版本 91.46;而对于 119:54 将比较 119.9,即大于 11; 102:41 会比作 102.68,也比 11 多。

或者您可以通过将固定值除以 24(一天中的小时数)而不是乘以时差来稍微简化它:

CASE
  WHEN abs(RM_LIVE.TRANSACTIONLOG.TIMESTAMP
    - RM_LIVE.CRWGNDACTTIME.GNDACTSTART) <= 11/24 THEN 'LESS"
ELSE 'MORE'
END AS "mORE/LESS",

【讨论】:

在大多数 recoders 中,如果日期是这样的,我会收到 -1:-2 -1:-3 16/JAN/2016 11:15:00 16/JAN/2016 12:44:00 16/JAN/2016 11:15:00 16/JAN/2016 12:50:00 另一件事,差异结果以文本形式出现,我如何转换数字或时间 @CricBuzz - 如果您想要 91:28 等,它不能是数字,您需要之前的十进制版本 91.46。或者将其拆分为两个数值,一个代表小时,一个代表分钟。并且 Oracle 没有单独的时间数据类型;最接近的是间隔,但不允许小时 > 23,如果不将其转换回 3 天 19 小时,其他任何东西都不会。您的客户端或应用程序必须解释该字符串。如果这不仅仅是为了展示,那么不确定你会用它做什么。 如果 作为字符串比较时它不大于 11,这是正在发生的事情。如果您想比较它,那么将其保留为小数会更容易。请不要像这样将代码放在 cmets 中,特别是当您已经将其添加到问题中时。尽管无论如何它与原始问题并不真正相关......

以上是关于以小时和分钟计算两个日期之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

两个日期之间的差异(以分钟为单位)

计算两个日期时间odoo 10之间的差异[重复]

在 Swift 中计算两个日期之间的差异

以分钟为单位计算两个日期之间的时间差

Java计算两个日期时间相差几天,几小时,几分钟等

Java计算两个日期时间相差几天,几小时,几分钟等