自1970年以来,将Sql Server DateTime转换为毫秒

时间:2014-03-04 10:42:08

标签: sql-server

我想将sql server datetime转换为毫秒。我尝试使用datediff函数转换它,如下所示:

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

但它给了我这个错误:

Msg 535,Level 16,State 0,Line 2 日期函数导致溢出。分隔两个日期/时间实例的日期部分数量太大。尝试使用具有不太精确的日期部分的datediff。

我不想这样做:

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

因为它不会给我准确的结果。有人可以帮帮我吗?

6 个答案:

答案 0 :(得分:5)

对于仍在寻找此项目的人,您可以使用DATEDIFF_BIG功能。这在SQL 2016 +,Azure

中受支持

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

答案 1 :(得分:4)

你确定需要它到毫秒(千分之一秒)吗?

请注意,1天= 86,400,000ms(是的,8640万)

1年=约316亿毫秒。

1970年(截至今天)44年前,大约是1.4万亿毫秒之前。

当然,bigint可以处理它,不幸的是你也达到DATEDIFF的限制,这是文档中的引用:

  

如果返回值超出int(-2,147,483,648到+2,147,483,647)的范围,则返回错误。对于毫秒,startdate和enddate之间的最大差异是24天,20小时,31分钟和23.647秒。第二,最大差异是68年。

所以,你可以安全地获得一段时间内的差异(只要你不会走得太远),然后你可以从今天开始计算毫秒数,例如:

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]

前两列只是为了显示所涉及的步骤。

答案 2 :(得分:2)

使用此查询可以获得自1970年以来的DateTime到毫秒

SELECT CAST(Datediff(s, '1970-01-01', GETUTCDATE()) AS BIGINT)*1000

答案 3 :(得分:1)

这是一个Microsoft SQL函数,它以毫秒为单位返回UTC时间(自1970年以来的毫秒数),其结果等于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

答案 4 :(得分:0)

选择Datediff_big(MS,' 1970-01-01',GETUTCDATE())

我确认了结果。

在匿名评论中找到mitchfincher.blogspot.com/2013/09/convert-sql-server-datetime-to.html

答案 5 :(得分:0)

这里有一些SQL代码可以完成这项工作。
假定数据库服务器的本地时间是中欧(夏/冬)时间(CET / CEST)。
(取决于您将UTC还是本地时间保存到datetime列中)

注意-夏时制
从冬季更改为夏季(3月底)
在三月的最后一个星期日早晨,时钟从02:00到03:00进行。
“一个人损失一个小时。”

从夏季更改为冬季(10月底)
在十月的最后一个星期日早晨,时钟从03:00推迟到02:00。
“一个人赢得一个小时。”

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