0

我想以 HH:MM 格式格式化部分日期(两个日期之间的差异)。

为此,我组装了以下逻辑:

LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' || LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00'))

我需要将此逻辑应用于多个间隔,因此最好使用函数将关键内容 DRY。

有没有办法在 SQL 语句中嵌入这个逻辑(可能使用 Java),而不必求助于创建 Oracle 函数?

** 编辑 **

DATE_DIFFERENCE 可以是负数并且大于 24 小时。如果负数,我想包括符号,但也代表小时和分钟的差异,即使 DATE_DIFFERENCE 大于 24 小时。

4

1 回答 1

2

从查询访问的 Java 函数比 SQL 函数要多得多,所以我不完全确定你的意思。您不能使用查询声明函数,因为您将混合 SQL 和 PL/SQL 上下文。

您的转换看起来不必要地复杂;你可以这样做:

substr(numtodsinterval(date_difference, 'DAY'), 12, 5)

numtodsinterval函数获取您的日期差异并将其转换为间隔数据类型,并substr获取涵盖小时和分钟的部分。

但它的行为略有不同,因为它会截断而不是四舍五入:

with tmp as (
    select to_date('2013-04-11 13:17:15', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-11 12:57:38', 'YYYY-MM-DD HH24:MI:SS')
        as date_difference
    from dual
    union all
    select to_date('2013-04-11 11:11:35', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-10 22:40:45', 'YYYY-MM-DD HH24:MI:SS') 
    from dual
    union all
    select to_date('2013-04-11 00:59:59', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 
    from dual
)
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' ||
        LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')),
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5)
from tmp;

LTRIM(T SUBSTR(NUMTODSINTERV
------- --------------------
00:20   00:19
12:31   12:30
00:00   00:59

这些的完整间隔是:

NUMTODSINTERVAL(DATE_DIFFERENCE,'DAY')
---------------------------------------------------------------------------
+000000000 00:19:37.000000000
+000000000 12:30:50.000000000
+000000000 00:59:59.000000000

所以很明显第一个会四舍五入到00:20,但截断到00:19。正如 Egor Skriptunoff 在评论中指出的那样,您对第三个的计算给出了错误的答案,这就是我现在将其包括在内的原因。

这将四舍五入,但会更长一些:

to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI')

我用过的文字中使用的实际日期date '2001-01-01'无关紧要,它可以是任何一天,trunc(sysdate)例如,您可以使用它。它只允许您将差异转换回一个DATE对象,然后您可以在其上使用内置round(date)函数。为了比较:

with tmp as (...)
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' ||
        LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')),
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5),
    to_char(trunc(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI'),
    to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI')
from tmp;

LTRIM(T SUBSTR(NUMTODSINTERV TO_CH TO_CH
------- -------------------- ----- -----
00:20   00:19                00:19 00:20
12:31   12:30                12:30 12:31
00:00   00:59                00:59 01:00

这些实际上都没有给你你想要的东西,一个嵌入式的临时功能,但至少如果逻辑更清晰,那么重用它可能就不那么担心了。不过,将其包装在 SQL 函数中可能仍然不是一个糟糕的选择。

于 2013-04-16T13:16:10.170 回答