I need to create a function in SQL Server 2008 that will mimic mysql's UNIX_TIMESTAMP()
.
9 Answers
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 ...
If you need millisecond precision (SQL Server 2016/13.x and later):
SELECT DATEDIFF_BIG(ms, '1970-01-01 00:00:00', DateField)

- 18,404
- 6
- 86
- 103
-
12This works great, but wow, come on Microsoft - how hard is it to just create a proper unix timestamp function! – Felix Eve Sep 26 '18 at 08:12
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:
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

- 50,140
- 28
- 121
- 140

- 14,165
- 5
- 50
- 83
-
i've tried the first one. executing "SELECT UNIX_TIMESTAMP(GETDATE());" returns "'UNIX_TIMESTAMP' is not a recognized built-in function name.". trying to run (again) the setup query returns "Msg 2714, Level 16, State 3, Procedure UNIX_TIMESTAMP, Line 12 There is already an object named 'UNIX_TIMESTAMP' in the database." – TheZver Jan 12 '12 at 15:13
-
1
-
the second worked fine. but trying to name it just as 'UNIX_TIMESTAMP' produced same results as described before. isn't there a way to make it named 'UNIX_TIMESTAMP' ? i'm trying to avoid modifying pretty much code, that needs to work with mysql AND mssql – TheZver Jan 12 '12 at 15:19
-
1You need to log into mssql with user with default schema dbo.That's all.http://msdn.microsoft.com/en-us/library/ms190387.aspx .If you have SQL Server management studio and 'sa' access you can setup it in 10 seconds. – rkosegi Jan 12 '12 at 15:21
-
" dbo.UNIX_TIMESTAMP(GETDATE()); " works, thanks. but it would still require modifying much code to switch between the functions according to the database being used – TheZver Jan 12 '12 at 15:22
-
Perhaps you can give ALTER example how to change the default schema for user? I spent much more then 10 seconds (about 10 minutes :) ) and still can't get it right. Thanks! – TheZver Jan 12 '12 at 15:29
-
Ok, finally found and changed it - but it still doesn't work. Any other ideas? – TheZver Jan 12 '12 at 15:32
-
Start SQL Server management studio.Go to Security -> Logins and find login which you are using.Set default database "master".Go to user mapping.There should be row for your database, user and default schema set to "dba".Is'n it? – rkosegi Jan 12 '12 at 15:38
-
It seems impossible. http://stackoverflow.com/questions/502949/is-it-possible-to-call-a-user-defined-function-without-the-schema-name – TheZver Jan 12 '12 at 15:44
-
2Be aware that unix timestamps count the number of seconds since 1970-01-01 at 00:00:00 UTC! That means, that if your SQL server is running local time, you may not get the correct unix timestamp using this approach. – Dan Aug 10 '18 at 10:57
-
GETUTCDATE() will return a UTC `datetime` with millisecond precision, supported since at least MSSQL 2012. If you need sub-millisecond precision, SYSUTCDATETIME() returns a UTC `datetime2(7)` timestamp. – J.D. Mallen Feb 06 '20 at 13:12
-
1The answer should be edited. `GETDATE()` is simply wrong, only `GetUTCDate()` is correct in regards to Unix timestamps! – Daniel Marschall Apr 09 '20 at 14:25
Sql Server 2016 and later have a DATEDIFF_BIG function that can be used to get the milliseconds.
SELECT DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())
Create a function
CREATE FUNCTION UNIX_TIMESTAMP()
RETURNS BIGINT
AS
BEGIN
RETURN DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())
END
And execute it
SELECT dbo.UNIX_TIMESTAMP()

- 1,875
- 19
- 27
-
1This should be the accepted answer. Using `GETDATE()` is wrong, `GetUTCDate()` is correct – Daniel Marschall Apr 09 '20 at 14:24
-
But does this work for all timezones? Will SELECT dbo.UNIX_TIMESTAMP() give me the time in my local timezone? Or will it give me the UTC time? – luisdev Nov 23 '20 at 07:59
For timestamp with milliseconds result I found this solution from here https://gist.github.com/rsim/d11652a8336137832df9:
SELECT (cast(DATEDIFF(s, '1970-01-01', GETUTCDATE()) as bigint)*1000+datepart(ms,getutcdate()))
Answer from @Rafe didn't work for me correctly (MSSQL 20212) - I got 9 seconds of difference.

- 89
- 5
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.)

- 4,823
- 1
- 38
- 34
-
For "-- the right way, for sql server 2008 and greater" I had to multiply the result by 1000 to remove the decimal points it was creating. Get the millisecond epoc after that. Works like a charm. Thanks!! – jymbo Jun 24 '17 at 14:27
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

- 78,642
- 66
- 377
- 442
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)

- 395
- 1
- 4
- 15
-
-
that is what saved me and the OP asked the same. if you want native timezone replace GETUTCDATE with GETDATE. however you will mess up the unix timestamp using it. – Rafe Nov 23 '20 at 09:52
If you have to deal with previous versions of SQL Server (<2016) and you only care for positive timestamps, I post here the solution I found for very distant dates (so you can get rid of the IF from @rkosegi's answer.
What I did was first calculating the difference in days and then adding the difference in seconds left.
CREATE FUNCTION [dbo].[UNIX_TIMESTAMP]
(
@inputDate DATETIME
)
RETURNS BIGINT
AS
BEGIN
DECLARE @differenceInDays BIGINT, @result BIGINT;
SET @differenceInDays = DATEDIFF(DAY, '19700101', @inputDate)
IF @differenceInDays >= 0
SET @result = (@differenceInDays * 86400) + DATEDIFF(SECOND, DATEADD(DAY, 0, DATEDIFF(DAY, 0, @inputDate)), @inputDate)
ELSE
SET @result = 0
RETURN @result
END

- 11
- 2
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());

- 12,966
- 14
- 47
- 68

- 2,775
- 1
- 15
- 11
-
1`GETDATE()` is wrong, only `GetUTCDate()` is correct in regards to Unix timestamps! – Daniel Marschall Apr 09 '20 at 14:26