UNIX_TIMESTAMP in SQL Server

后端 未结 8 1952
陌清茗
陌清茗 2020-12-01 15:45

I need to create a function in SQL Server 2008 that will mimic mysql\'s UNIX_TIMESTAMP().

Thanks in advance !

相关标签:
8条回答
  • 2020-12-01 16:20

    If you're not bothered about dates before 1970, or millisecond precision, just do:

    -- SQL Server
    SELECT DATEDIFF(s, '1970-01-01 00:00:00', DateField)
    

    Almost as simple as MySQL's built-in function:

    -- MySQL
    SELECT UNIX_TIMESTAMP(DateField);
    

    Other languages (Oracle, PostgreSQL, etc): How to get the current epoch time in ...

    0 讨论(0)
  • 2020-12-01 16:21

    When called to Scalar-valued Functions can use following syntax

    Function Script :

    USE [Database]
    GO
    
    /****** Object:  UserDefinedFunction [dbo].[UNIX_TIMESTAMP]  ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE FUNCTION [dbo].[UNIX_TIMESTAMP] (
    @ctimestamp datetime
    )
    RETURNS integer
    AS
    BEGIN
      /* Function body */
      declare @return integer
    
      SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)
    
      return @return
    END 
    GO
    

    Call Function :

    SELECT dbo.UNIX_TIMESTAMP(GETDATE());
    
    0 讨论(0)
  • 2020-12-01 16:24

    Try this post: https://web.archive.org/web/20141216081938/http://skinn3r.wordpress.com/2009/01/26/t-sql-datetime-to-unix-timestamp/

    CREATE FUNCTION UNIX_TIMESTAMP (
    @ctimestamp datetime
    )
    RETURNS integer
    AS 
    BEGIN
      /* Function body */
      declare @return integer
    
      SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)
    
      return @return
    END
    

    or this post:

    http://mysql.databases.aspfaq.com/how-do-i-convert-a-sql-server-datetime-value-to-a-unix-timestamp.html

    code is as follows:

    CREATE FUNCTION dbo.DTtoUnixTS 
    ( 
        @dt DATETIME 
    ) 
    RETURNS BIGINT 
    AS 
    BEGIN 
        DECLARE @diff BIGINT 
        IF @dt >= '20380119' 
        BEGIN 
            SET @diff = CONVERT(BIGINT, DATEDIFF(S, '19700101', '20380119')) 
                + CONVERT(BIGINT, DATEDIFF(S, '20380119', @dt)) 
        END 
        ELSE 
            SET @diff = DATEDIFF(S, '19700101', @dt) 
        RETURN @diff 
    END
    

    Sample usage:

    SELECT dbo.DTtoUnixTS(GETDATE()) 
    -- or 
    SELECT UnixTimestamp = dbo.DTtoUnixTS(someColumn) 
        FROM someTable
    
    0 讨论(0)
  • 2020-12-01 16:31

    Necromancing.
    The ODBC-way:

    DECLARE @unix_timestamp varchar(20)
    -- SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20)) 
    
    IF CURRENT_TIMESTAMP >= '20380119' 
    BEGIN 
        SET @unix_timestamp = CAST
        (
            CAST
            (
                {fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, {d '2038-01-19'})} 
                AS bigint
            )  
            + 
            CAST
            (
                {fn timestampdiff(SQL_TSI_SECOND,{d '2038-01-19'}, CURRENT_TIMESTAMP)}
                AS bigint
            ) 
        AS varchar(20)
        ) 
    END 
    ELSE 
        SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20))
    
    PRINT @unix_timestamp
    
    0 讨论(0)
  • 2020-12-01 16:33

    Here's a single-line solution without declaring any function or variable:

    SELECT CAST(CAST(GETUTCDATE()-'1970-01-01' AS decimal(38,10))*86400000.5 as bigint)
    
    0 讨论(0)
  • 2020-12-01 16:40

    I often need a unix timestamp with millisecond precision. The following will give you the current unixtime as FLOAT; wrap per answers above to get a function or convert arbitrary strings.

    The DATETIME datatype on SQL Server is only good to 3 msec, so I have different examples for SQL Server 2005 and 2008+. Sadly there is no DATEDIFF2 function, so various tricks are required to avoid DATEDIFF integer overflow even with 2008+. (I can't believe they introduced a whole new DATETIME2 datatype without fixing this.)

    For regular old DATETIME, I just use a sleazy cast to float, which returns (floating point) number of days since 1900.

    Now I know at this point, you are thinking WHAT ABOUT LEAP SECONDS?!?! Neither Windows time nor unixtime really believe in leap seconds: a day is always 1.00000 days long to SQL Server, and 86400 seconds long to unixtime. This wikipedia article discusses how unixtime behaves during leap seconds; Windows I believe just views leap seconds like any other clock error. So while there is no systematic drift between the two systems when a leap second occurs, they will not agree at the sub-second level during and immediately following a leap second.

    -- the right way, for sql server 2008 and greater
    declare @unixepoch2 datetime2;
    declare @now2 Datetime2;
    declare @days int;
    declare @millisec int;
    declare @today datetime2;
    set @unixepoch2 = '1970-01-01 00:00:00.0000';
    set @now2 = SYSUTCDATETIME();
    set @days = DATEDIFF(DAY,@unixepoch2,@now2);
    set @today = DATEADD(DAY,@days,@unixepoch2);
    set @millisec = DATEDIFF(MILLISECOND,@today,@now2);
    select (CAST (@days as float) * 86400) + (CAST(@millisec as float ) / 1000)
      as UnixTimeFloatSQL2008
    
    -- Note datetimes are only accurate to 3 msec, so this is less precise 
    -- than above, but works on any edition of SQL Server.
    declare @sqlepoch datetime;
    declare @unixepoch datetime;
    declare @offset float;
    set @sqlepoch = '1900-01-01 00:00:00';
    set @unixepoch = '1970-01-01 00:00:00';
    set @offset = cast (@sqlepoch as float) - cast (@unixepoch as float);
    select ( cast (GetUTCDate() as float) + @offset) * 86400 
      as UnixTimeFloatSQL2005;
    
    -- Future developers may hate you, but you can put the offset in
    -- as a const because it isn't going to change. 
    declare @sql_to_unix_epoch_in_days float;
    set @sql_to_unix_epoch_in_days = 25567.0;
    select ( cast (GetUTCDate() as float) - @sql_to_unix_epoch_in_days) * 86400.0 
      as UnixTimeFloatSQL2005MagicNumber;
    

    FLOATs actually default to 8-byte doubles on SQL Server, and therefore superior to 32-bit INT for many use cases. (For example, they won't roll over in 2038.)

    0 讨论(0)
提交回复
热议问题