Hive/SQL 将毫秒转换为 DDDD:HH:mm:ss 时出错

Hive/SQL Error when converting milliseconds to DDDD:HH:mm:ss

我有一个以毫秒为单位的输出太大,无法用 HH:mm:ss 格式描述,我需要扩展为 DDDD:HH:mm:ss.

我目前使用的代码只适用于大数:

select from_unixtime(cast(floor(2513702864/1000) as bigint), 'DDDD:HH:mm:ss');

给出:0030:02:15:02,这是正确的

select from_unixtime(cast(floor(17259/1000) as bigint), 'DDDD:HH:mm:ss');

给出:0001:00:00:17,这是不正确的。

select from_unixtime(cast(floor(127259/1000) as bigint), 'DDDD:HH:mm:ss');

给出:0001:00:02:07,这也不正确。

在处理更小的毫秒数时,如何修复 DDDD 部分的错误 1?

逻辑很简单。 BIGINT 时间戳是从 Unix Epoch (1970-01-01 00:00:00 UTC) 传递的秒数或毫秒数。

要获得毫秒部分,请使用 (ts % 1000) - returns 除以 1000 后的提醒

要获得总秒数,请使用 (ts div 1000) - returns 整数部分,所有其他数字都将根据此数字计算:天、小时、分钟、秒。

天:(ts div 1000) div 86400 - returns 总秒数除以一天中的秒数后的整数部分

计算全天后剩余小时数:计算天数后取提醒 ((ts div 1000) % 86400) 并除以小时秒数,取整数部分 (((ts div 1000) % 86400) div 3600)

以此类推

演示:

with your_data as (
select 1 id, bigint(2513702864) ts union all
select 2, bigint(17259) union all
select 3,bigint(127259) union all
select 4,bigint(1272) union all
select 5,bigint(127)
)

select --format output as required. For example days:hours:minutes:seconds.millis
       concat(days,':',hours,':',minutes,':',seconds,'.',millis)
from
(
select ((ts div 1000) div 86400) days, --number of whole days
       lpad(((ts div 1000) % 86400) div 3600, 2, 0) hours, --whole hours left
       lpad((((ts div 1000) % 86400) % 3600) div 60, 2, 0) minutes, --whole minutes left
       lpad((((ts div 1000) % 86400) % 3600) % 60, 2, 0) seconds, --seconds left
       (ts % 1000) as millis
  from your_data
)s

结果:

1 29:02:15:02.864 --29 whole days, 2 hours, 15 minutes, 2 seconds, 864 millis
2 0:00:00:17.259 --17 whole seconds and 259 millis
3 0:00:02:07.259 --two whole minutes, 7 seconds and 259 millis
4 0:00:00:01.272 --one whole second and millis
5 0:00:00:00.127 --we have only milliseconds

现在您可以看到此计算与 from_unixtime returns 之间的区别。 对于记录 id=1,整天数是 29。为什么 from_unixtime returns 30(对于 pattern 'D')?因为 29 整天过去了,我们在新的一天 30 中是 2 小时 15 分 2 秒 864 英里。换句话说,from_unixtime returns 时间戳格式和我查询中的计算 returns 间隔格式,“一年中的某一天”和“过去的每一天”是不同的东西。

希望,现在天明了

另见类似问题:

如果您需要将以毫秒为单位的 bigint 时间戳转换为保留毫秒的字符串 (yyyy-MM-dd HH:mm:ss.SSS),请使用:

select concat(from_unixtime(ts div 1000), '.', (ts  % 1000)) as timestamp_with_millis
  from (select bigint(2513702864)  as ts) s

结果:

1970-01-30 02:15:02.864