22

I want to convert sql server datetime to milliseconds . I tried to convert it with datediff function as below :

select cast(Datediff(ms, '1970-01-01',GETUTCDATE()) AS bigint)

But it's giving me this error:

Msg 535, Level 16, State 0, Line 2 The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

I don't wanna do it like this :

select cast(Datediff(minute, '1970-01-01',GETUTCDATE()) AS bigint)*60*1000

Because it won't give me accurate results. Can somebody please help me on this?

Nagaraj S
  • 13,316
  • 6
  • 32
  • 53
user3363908
  • 221
  • 1
  • 2
  • 4

8 Answers8

27

For the people still looking for this, you can use the DATEDIFF_BIG function. This is supported in SQL 2016+, Azure

https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-big-transact-sql

  • 6
    e.g. `SELECT DATEDIFF_BIG(MILLISECOND, '1970-01-01', GETDATE());` – Fawad Raza Aug 16 '20 at 17:04
  • This works great for me, and has the added benefit of retaining the time part of the DateTime value. The method below, CAST(DATEDIFF..., also works but doesn't seem to include the time portion. – molaro Aug 21 '20 at 19:12
10

With this query can you get the DateTime to Milliseconds Since 1970

SELECT CAST(Datediff(s, '1970-01-01', GETUTCDATE()) AS BIGINT)*1000
Mise
  • 3,267
  • 1
  • 22
  • 22
  • I have used this a lot, and it works great if you only need the Date. When I used this one a table column where I also needed the time, I always got 12:00 PM. Using the answer above, DATEDIFF_BIG() gets an epoch with the time intact – molaro Aug 21 '20 at 19:10
4

select Datediff_big(MS, '1970-01-01', GETUTCDATE())

I confirmed the result.

Found at mitchfincher.blogspot.com/2013/09/convert-sql-server-datetime-to.html in an anonymous comment.

Reid
  • 3,170
  • 2
  • 23
  • 37
3

Are you sure you need it down to milliseconds (thousandths of a second)?

Be aware that 1 day = 86,400,000ms (yes, 86.4 million)

1 year = approx 31.6 billion milliseconds.

1970 was (as of today) 44 years ago, so that is approx 1.4 trillion milliseconds ago.

Sure, a bigint can handle it, unfortunately you also hit a limit of DATEDIFF, here's a quote from the documentation:

If the return value is out of range for int (-2,147,483,648 to +2,147,483,647), an error is returned. For millisecond, the maximum difference between startdate and enddate is 24 days, 20 hours, 31 minutes and 23.647 seconds. For second, the maximum difference is 68 years.

So, you're safe getting the difference in seconds for a while (as long as you don't go too far into the future), and you could then count milliseconds from the start of today, e.g.:

SELECT 
  CAST(DATEDIFF(second, '1970-01-01', CAST(GetUtcDate() AS date)) AS bigint)
    AS [SecondsToStartOfDay], 
  DATEDIFF(ms, CAST(GetUtcDate() AS date), GetUtcDate())
    AS [MillisecondsSinceStartOfDay],
  (CAST(DATEDIFF(second, '1970-01-01', CAST(GetUtcDate() AS date)) AS bigint)*1000) 
  + DATEDIFF(ms, CAST(GetUtcDate() AS date), GetUtcDate()) 
    AS [Milliseconds]

The first two columns are just to show the steps involved.

Timothy Walters
  • 16,866
  • 2
  • 41
  • 49
  • 1
    The different calls to the date function can return different results which means this answer can be 24 hours out if run at midnight. – Martin Smith Jun 03 '14 at 09:09
  • 1
    The current value of `GetUtcDate()` could be saved to a variable and then reused if that is an issue. – Timothy Walters Jun 03 '14 at 20:43
  • how can i get the date only in milliseconds like this '1459881000000' you can check the date on this site https://currentmillis.com/ – Ajinkya Jul 15 '16 at 11:33
1

Here is a Microsoft SQL function that returns UTC time in milliseconds(Milliseconds since 1970) its result is equal to Java.currentTimeMillis()

CREATE FUNCTION dbo.currentTimeMilliseconds()
  RETURNS BIGINT
  WITH EXECUTE AS CALLER
AS
  BEGIN

    DECLARE @t datetime = CONVERT (datetime, GETUTCDATE());
    DECLARE @days BIGINT = Datediff(day, '1970-01-01',@t);
    DECLARE @t_hours BIGINT = DATEPART(HOUR, @t);
    DECLARE @t_minuts BIGINT = DATEPART(MINUTE, @t);
    DECLARE @t_seconds BIGINT = DATEPART(SECOND, @t);
    DECLARE @t_miliseconds BIGINT = DATEPART(MILLISECOND, @t);

    RETURN @days * 1000 * 60 * 60 * 24 + @t_hours * 60 *60 *1000 + @t_minuts * 60 * 1000 + @t_seconds * 1000 + @t_miliseconds;
  END
GO
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
1

Here some SQL-code that does the job.
It assumes the DB server's local-time is Central European (Summer/Winter) Time (CET/CEST).
(it depends on whether you save UTC or local-time into your datetime-columns)

Note - Daylight saving time:
Change from winter-time to summer time (at end of march)
At the last sunday-morning in March, the clocks are put forward from 02:00 to 03:00 o'clock.
"One loses an hour. "

Change from summter-time to winter-time (at end of October)
At the last sunday morning in October, the clocks are being put backward from 03:00 to 02:00 o'clock.
"One wins an hour."

PRINT 'Begin Executing "01_fu_dtLastSundayInMonth.sql"' 

GO 



IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_dtLastSundayInMonth]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
    EXECUTE(N'CREATE FUNCTION [dbo].[fu_dtLastSundayInMonth]() RETURNS int BEGIN RETURN 0 END ')
END 
GO 



/*
SET DATEFIRST 3; -- Monday

WITH CTE AS (

    SELECT 1 AS i, CAST('20190101' AS datetime) AS mydate  
    UNION ALL 

    SELECT i+1 AS i, DATEADD(month, 1, CTE.mydate) AS mydate 
    FROM CTE WHERE i < 100 
)

SELECT -666 AS i, dbo.fu_dtLastSundayInMonth('17530101') AS lastSundayInMonth, dbo.fu_dtLastSundayInMonth('17530101') AS Control 

UNION ALL 

SELECT -666 AS i, dbo.fu_dtLastSundayInMonth('99991231') AS lastSundayInMonth, dbo.fu_dtLastSundayInMonth('99991231') AS Control 

UNION ALL 

SELECT 
     mydate 
    ,dbo.fu_dtLastSundayInMonth(mydate) AS lastSundayInMonth 
    ,dbo.fu_dtLastSundayInMonth(mydate) AS lastSundayInMonth 
    ,CAST(NULL AS datetime) AS Control
    --,DATEADD(day,DATEDIFF(day,'19000107', DATEADD(MONTH, DATEDIFF(MONTH, 0, mydate, 30))/7*7,'19000107') AS Control 
FROM CTE 

*/


-- =====================================================================
-- Author:        Stefan Steiger
-- Create date:   01.03.2019
-- Last modified: 01.03.2019
-- Description:   Return Datum von letztem Sonntag im Monat 
--                mit gleichem Jahr und Monat wie @in_DateTime
-- =====================================================================
ALTER FUNCTION [dbo].[fu_dtLastSundayInMonth](@in_DateTime datetime )
RETURNS DateTime
AS
BEGIN
    -- Abrunden des Eingabedatums auf 00:00:00 Uhr
    DECLARE @dtReturnValue AS DateTime  
    -- 26.12.9999   SO
    IF @in_DateTime >= CAST('99991201' AS datetime) 
        RETURN CAST('99991226' AS datetime); 

    -- @dtReturnValue is now last day of month 
    SET @dtReturnValue = DATEADD 
        (
             DAY 
            ,-1
            ,DATEADD
            (
                 MONTH
                ,1
                ,CAST(CAST(YEAR(@in_DateTime) AS varchar(4)) + RIGHT('00' + CAST(MONTH(@in_DateTime) AS varchar(2)), 2) + '01' AS datetime) 
            )
        )
    ;

    -- SET DATEFIRST 1 -- Monday - Super easy ! 
    -- SET DATEFIRST != 1 - PHUK THIS ! 
    SET @dtReturnValue = DATEADD
                        (
                            day
                            ,
                             -
                             (

                                (
                                    -- DATEPART(WEEKDAY, @lastDayofMonth) -- with SET DATEFIRST 1 
                                    DATEPART(WEEKDAY, @dtReturnValue) + @@DATEFIRST - 2 % 7 + 1 
                                )
                                %7
                            )
                            , @dtReturnValue
    );

    RETURN @dtReturnValue; 
END


GO



GO 


PRINT 'Done Executing "01_fu_dtLastSundayInMonth.sql"' 


GO 





PRINT 'Begin Executing "02_fu_dtIsCEST.sql"' 

GO 



IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_dtIsCEST]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
    EXECUTE(N'CREATE FUNCTION [dbo].[fu_dtIsCEST]() RETURNS int BEGIN RETURN 0 END ')
END 
GO 




-- =====================================================================
-- Author:        Stefan Steiger
-- Create date:   01.03.2019
-- Last modified: 01.03.2019
-- Description:   Ist @in_DateTime Mitteleuropäische Sommerzeit ? 
-- =====================================================================
-- SELECT dbo.fu_dtIsCEST('2019-03-31T01:00:00'), dbo.fu_dtIsCEST('2019-03-31T04:00:00') 
ALTER FUNCTION [dbo].[fu_dtIsCEST](@in_DateTime datetime )
RETURNS bit 
AS
BEGIN
    DECLARE @dtReturnValue AS bit   

    -- https://www.linker.ch/eigenlink/sommerzeit_winterzeit.htm

    -- Umstellung von Winterzeit auf Sommerzeit (Ende März):  
    -- Am letzten Sonntagmorgen im März werden die Uhren von 02:00 auf 03:00 Uhr vorgestellt. 
    -- Man verliert eine Stunde. 

    -- Umstellung von Sommerzeit auf Winterzeit (Ende Oktober): 
    -- Am letzten Sonntagmorgen im Oktober werden die Uhren von 03:00 auf 02:00 Uhr zurückgestellt. 
    -- Man gewinnt eine Stunde.

    DECLARE @beginSummerTime datetime 
    SET @beginSummerTime = dbo.fu_dtLastSundayInMonth(DATEADD(MONTH, 2, DATEADD(YEAR, YEAR(@in_DateTime)-1900, 0)) )  
    SET @beginSummerTime = DATEADD(HOUR, 2, @beginSummerTime) 

    DECLARE @beginWinterTime datetime 
    SET @beginWinterTime = dbo.fu_dtLastSundayInMonth(DATEADD(MONTH, 9, DATEADD(YEAR, YEAR(@in_DateTime)-1900, 0)) )   
    SET @beginWinterTime = DATEADD(HOUR, 2, @beginWinterTime) 

    SET @dtReturnValue = 0; 
    IF @in_DateTime >= @beginSummerTime AND @in_DateTime < @beginWinterTime 
    BEGIN 
        SET @dtReturnValue = 1;
    END 

    RETURN @dtReturnValue;
END


GO



GO 


PRINT 'Done Executing "02_fu_dtIsCEST.sql"' 


GO 





PRINT 'Begin Executing "03_fu_dtToEcmaTimeStamp.sql"' 

GO 



IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_dtToEcmaTimeStamp]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
    EXECUTE(N'CREATE FUNCTION [dbo].[fu_dtToEcmaTimeStamp]() RETURNS int BEGIN RETURN 0 END ')
END 
GO 




-- =====================================================================
-- Author:        Stefan Steiger
-- Create date:   01.03.2019
-- Last modified: 01.03.2019
-- Description:   Ist @in_DateTime Mitteleuropäische Sommerzeit ? 
-- =====================================================================
-- SELECT dbo.fu_dtToEcmaTimeStamp('2019-03-31T01:00:00', 1), dbo.fu_dtToEcmaTimeStamp('2019-03-31T04:00:00', 1) 
ALTER FUNCTION [dbo].[fu_dtToEcmaTimeStamp](@in_DateTime datetime, @in_convert_to_utc bit)
RETURNS bigint 
AS
BEGIN
    DECLARE @dtReturnValue AS bigint    

    IF @in_convert_to_utc = 1 
    BEGIN
        SET @in_DateTime = 
        CASE WHEN dbo.fu_dtIsCEST(@in_DateTime) = 1 
            THEN DATEADD(HOUR, -2, @in_DateTime) 
            ELSE DATEADD(HOUR, -1, @in_DateTime) 
        END;
    END 

    SET @dtReturnValue = 
        CAST
        (
            DATEDIFF
            (
                HOUR
                ,CAST('19700101' AS datetime)
                ,@in_DateTime 
            )
            AS bigint
        ) *60*60*1000
        + 
        DATEDIFF
        (
             MILLISECOND 
            ,CAST(FLOOR(CAST(@in_DateTime AS float)) AS datetime) 
            ,@in_DateTime 
        ) % (60*60*1000)
    ;

    RETURN @dtReturnValue;
END


GO



GO 


PRINT 'Done Executing "03_fu_dtToEcmaTimeStamp.sql"' 


GO 





PRINT 'Begin Executing "04_fu_dtFromEcmaTimeStamp.sql"' 

GO 



IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_dtFromEcmaTimeStamp]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
    EXECUTE(N'CREATE FUNCTION [dbo].[fu_dtFromEcmaTimeStamp]() RETURNS int BEGIN RETURN 0 END ')
END 
GO 



-- =====================================================================
-- Author:        Stefan Steiger
-- Create date:   01.03.2019
-- Last modified: 01.03.2019
-- Description:   Ist @in_DateTime Mitteleuropäische Sommerzeit ? 
-- =====================================================================
-- SELECT dbo.fu_dtFromEcmaTimeStamp('1551437088122', 1), dbo.fu_dtFromEcmaTimeStamp('1554069600000', 1) 
ALTER FUNCTION [dbo].[fu_dtFromEcmaTimeStamp](@in_timestamp bigint, @in_convert_to_localtime bit)
RETURNS datetime 
AS
BEGIN
    DECLARE @dtReturnValue AS datetime      
    DECLARE @hours int 
    SET @hours = @in_timestamp /(1000*60*60);

    DECLARE @milliseconds int 
    SET @milliseconds = @in_timestamp - (@in_timestamp /(1000*60*60))*(1000*60*60);


    SET @dtReturnValue = DATEADD 
                        (
                            MILLISECOND, @milliseconds, 
                            DATEADD(hour, @hours, CAST('19700101' AS datetime)) 
                        ) 


    IF @in_convert_to_localtime = 1 
    BEGIN
        SET @dtReturnValue = DATEADD(HOUR, 1, @dtReturnValue) 
        SET @dtReturnValue = 
                                CASE WHEN dbo.fu_dtIsCEST(@dtReturnValue) = 1 
                                    THEN DATEADD(HOUR, 1, @dtReturnValue) 
                                    ELSE @dtReturnValue 
                                END;
    END 

    RETURN @dtReturnValue;
END


GO



GO 


PRINT 'Done Executing "04_fu_dtFromEcmaTimeStamp.sql"' 


GO 
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
1

For Sql Server before 2016 (e.g., 2008, 2012 et al), the code below may be a more acceptable approximation than just multiplying the result by 1000.

CREATE FUNCTION [dbo].[datetimeToUTCMilliseconds] (@ctimestamp as datetime) 
RETURNS bigint
AS
BEGIN
  /* Function body */
  declare @return bigint
   
  SELECT @return = (cast(DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp) as bigint) * 1000) + DATEPART(MILLISECOND, @ctimestamp);
   
  return @return
END

So you can use the relevant part below to convert sql server datetime to milliseconds:

SELECT (cast(DATEDIFF(SECOND,{d '1970-01-01'}, @yourdatetime) as bigint) * 1000) + DATEPART(MILLISECOND, @yourdatetime);
Collei Inc.
  • 46
  • 1
  • 5
0

For SQL Server 2016, I created 2 functions:

create or alter function dbo.ufn_unixTime2LocalTime
(
     @UnixTimeStamp bigint
    ,@seconds_only bit = 0
) returns datetime
as
begin;
    declare @LocalTimeOffset bigint = datediff_big(millisecond,getdate(),getutcdate());
    declare @AdjustedTimeStamp bigint = (@UnixTimeStamp * iif(@seconds_only = 1,1000,1)) - @LocalTimeOffset;
    return dateadd(millisecond, @AdjustedTimeStamp % 1000, dateadd(second,@AdjustedTimeStamp / 1000, '19700101'));
end;
go
create or alter function dbo.ufn_localTime2UnixTime
(
     @localTime datetime
    ,@seconds_only bit = 0
) returns bigint
as
begin;
    declare @LocalTimeOffset bigint = datediff_big(millisecond,getdate(),getutcdate());
    return datediff_big(millisecond,'19700101',dateadd(millisecond,@LocalTimeOffset,@localTime)) / iif(@seconds_only = 1,1000,1);
end;
go
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103