Reputation: 45
I have UNIX duration in ms, that needs to be converted to human readable format. In Postgres it is possible to do using INTERVAL type, but how can it be done in Snowflake? The challenge is that some of those values can exceed 24h. I've checked solution to a similar problem (with adjustments to ms) on Snowflake forum. But it doesnt support time > 24h.
Sample data:
7200000 -- 2h
28800000 --8h
1800000 -- 30min
252000000 -- 70h
86400000 -- 24h
3593314 -- 59min 53sec
So that the desired output would look like:
02:00:00
08:00:00
00:30:00
70:00:00
24:00:00
00:59:53
Maybe I am bad at searching, but so far I wasnt able to find a solution for this issue.
Solution that works in Postgres SELECT time_unix::bigint * INTERVAL '1 ms'
Upvotes: 0
Views: 304
Reputation: 25903
select *
,floor(ms/3600000) as hh
,floor((ms%3600000)/60000) as mm
,floor((ms%60000)/1000) as ss
,nullifzero(hh) as a1
,nullifzero(mm) as a2
,nullifzero(ss) as a3
,trim(nvl(a1||'h ','') || nvl(a2||'m ','') || nvl(a3||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
gives:
MS | WANTED | HH | MM | SS | A1 | A2 | A3 | R |
---|---|---|---|---|---|---|---|---|
7,200,000 | 2h | 2 | 0 | 0 | 2 | 2h | ||
28,800,000 | 8h | 8 | 0 | 0 | 8 | 8h | ||
1,800,000 | 30min | 0 | 30 | 0 | 30 | 30m | ||
252,000,000 | 70h | 70 | 0 | 0 | 70 | 70h | ||
86,400,000 | 24h | 24 | 0 | 0 | 24 | 24h | ||
3,593,314 | 59min 53sec | 0 | 59 | 53 | 59 | 53 | 59m 53s |
thus:
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
gives:
MS | WANTED | R |
---|---|---|
7,200,000 | 2h | 2h |
28,800,000 | 8h | 8h |
1,800,000 | 30min | 30m |
252,000,000 | 70h | 70h |
86,400,000 | 24h | 24h |
3,593,314 | 59min 53sec | 59m 53s |
select *
,trim(nvl(nullifzero(floor(ms/3600000))||'h ','') || nvl(nullifzero(floor((ms%3600000)/60000))||'m ','') || nvl(nullifzero(floor((ms%60000)/1000))||'s','')) as r
,lpad(floor(ms/3600000), 2, 0) || ':' || lpad(floor((ms%3600000)/60000), 2, 0) || ':' || lpad(floor((ms%60000)/1000), 2, 0) as r2
from values
(7200000, '2h'),
(28800000 , '8h'),
(1800000, '30min'),
(252000000, '70h'),
(86400000, '24h'),
(3593314, '59min 53sec')
t(ms, wanted)
MS | WANTED | R | R2 |
---|---|---|---|
7,200,000 | 2h | 2h | 02:00:00 |
28,800,000 | 8h | 8h | 08:00:00 |
1,800,000 | 30min | 30m | 00:30:00 |
252,000,000 | 70h | 70h | 70:00:00 |
86,400,000 | 24h | 24h | 24:00:00 |
3,593,314 | 59min 53sec | 59m 53s | 00:59:53 |
Upvotes: 0
Reputation: 10039
Wondering if someone can come up with a worse solution :)
create or replace function pginterval( TIME number )
returns varchar
language sql
as
$$
select LPAD( (extract( day from to_timestamp( TIME, 3 )) - 1 ) * 24 + extract( hour from to_timestamp( TIME, 3 )), 2, '0' )
|| ':' || right( to_timestamp( TIME, 3 )::time, 5 )
$$;
select pginterval( x )
from values
(7200000),
(28800000),
(1800000),
(252000000),
(86400000),
(3593314) tmp (x);
PGINTERVAL( X ) |
---|
02:00:00 |
08:00:00 |
00:30:00 |
70:00:00 |
24:00:00 |
00:59:53 |
Upvotes: 1