Oracle 有一个区间数据类型,您可以将持续时间转换成它,但您不能真正格式化它。最简单的方法是使用 mod 和 trunc 将值分解为完整的小时和分钟,以及剩余的秒数。
一些样本数据:
with t (duration) as (
select 59 from dual
union all select 60 from dual
union all select 61 from dual
union all select 3599 from dual
union all select 3600 from dual
union all select 86399 from dual
)
select duration,
numtodsinterval(duration, 'SECOND') as interval_value,
'PT'
|| case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end
|| case when trunc(duration/3600) > 0 or trunc(mod(duration, 3600)/60) > 0
then trunc(mod(duration, 3600)/60) || 'M' end
|| trunc(mod(duration, 60)) || 'S' as iso_value
from t;
DURATION INTERVAL_VAL ISO_VALUE
---------- ------------ ------------
59 0 0:0:59.0 PT59S
60 0 0:1:0.0 PT1M0S
61 0 0:1:1.0 PT1M1S
3599 0 0:59:59.0 PT59M59S
3600 0 1:0:0.0 PT1H0M0S
86399 0 23:59:59.0 PT23H59M59S
我假设持续时间永远不会超过 24 小时,并且您只需要整秒;但如有必要,可以处理更长的持续时间和更高的精度。
我也猜你想排除最高的可选部分,所以你不会显示 0H 说;但是显示小时后,即使分钟和秒为零,您也想显示分钟和秒。如果没有,您可以调整(或删除)case 语句。
始终显示所有三个部分:
select duration,
numtodsinterval(duration, 'SECOND') as interval_value,
'PT' || trunc(duration/3600) || 'H'
|| trunc(mod(duration, 3600)/60) || 'M'
|| trunc(mod(duration, 60)) || 'S' as iso_value
from t;
DURATION INTERVAL_VAL ISO_VALUE
---------- ------------ ------------
59 0 0:0:59.0 PT0H0M59S
60 0 0:1:0.0 PT0H1M0S
61 0 0:1:1.0 PT0H1M1S
3599 0 0:59:59.0 PT0H59M59S
3600 0 1:0:0.0 PT1H0M0S
86399 0 23:59:59.0 PT23H59M59S
从不显示零部分:
select duration,
numtodsinterval(duration, 'SECOND') as interval_value,
'PT'
|| case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end
|| case when trunc(mod(duration, 3600)/60) > 0 then trunc(mod(duration, 3600)/60) || 'M' end
|| case when trunc(mod(duration, 60)) > 0 then trunc(mod(duration, 60)) || 'S' end
as iso_value
from t;
DURATION INTERVAL_VAL ISO_VALUE
---------- ------------ ------------
59 0 0:0:59.0 PT59S
60 0 0:1:0.0 PT1M
61 0 0:1:1.0 PT1M1S
3599 0 0:59:59.0 PT59M59S
3600 0 1:0:0.0 PT1H
86399 0 23:59:59.0 PT23H59M59S