14

I need convert a millisecond value, 85605304.3587 to a value like 0d 18h 21m. No idea on how to start that, is there something similar to a TimeSpan in SQL like there is in C#?

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
sd_dracula
  • 3,796
  • 28
  • 87
  • 158
  • 3
    Which [DBMS](https://en.wikipedia.org/wiki/DBMS) are you using? Postgres? Oracle? The data type in standard SQL (which is what the `sql` tag refers to) would be `interval` –  Jul 17 '17 at 14:25
  • SQL 2017 is what I am using – sd_dracula Jul 17 '17 at 14:34
  • 1
    There is no standard named "SQL 2017" but I guess you meant "SQL **Server** 2017" –  Jul 17 '17 at 14:39
  • The equivalent to `TimeSpan` is `time` but it stores only the *time of day*, not a duration. That means you can't specify times greater than 24 hours. `TimeSpan` can be stored directly into a `time` field – Panagiotis Kanavos Jul 17 '17 at 14:45
  • Where does this value come from? What is its range? Why not store it into a `time` field directly? – Panagiotis Kanavos Jul 17 '17 at 14:45

3 Answers3

26

You can do the calculation explicitly. I think it is:

select floor(msvalue / (1000 * 60 * 60 * 24)) as days,
       floor(msvalue / (1000 * 60 * 60)) % 24 as hours,
       floor(msvalue / (1000 * 60)) % 60 as minutes

Note: Some databases use mod instead of %.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
2

In MS SQL SERVER you can use next code:

with cte as (
    select cast(85605304.3587 as int) / 1000 / 60 as [min]
), cte2 as (
    select 
        cast([min] % 60 as varchar(max)) as minutes,
        cast(([min] / 60) % 24 as varchar(max)) as hours,
        cast([min] / (60 * 24) as varchar(max)) as days
    from cte
)
select concat(days, 'd ', hours, 'h ', minutes, 'm') as tm
from cte2
Evgeny
  • 597
  • 2
  • 7
  • 16
2

Using native date & time functions, maybe:

SELECT
    AsDateTime = DATEADD(MILLISECOND, 85605304, 0)
  , AsDateTime2 = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, DATEADD(MILLISECOND, 85605304, CONVERT(datetime2, CONVERT(datetime, 0)))))
-- Incorrect datetime2 approach I initially did, has some precision loss, probably due to datetime's millisecond issue with 0's, 3's, and 7.'s
--SELECT DontDoThis = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, CONVERT(datetime2, DATEADD(MILLISECOND, 85605304, 0))))

datetime covers only 3 digits beyond seconds, while datetime2 will maintain 7 digits. Perhaps other ways that give date-like objects exist, I wouldn't know.

KtX2SkD
  • 752
  • 4
  • 12