I want to convert UTC milliseconds to DateTime in SQL server.
This can easily be done in C# by following code:
DateTime startDate = new DateTime(1970, 1, 1).AddMilliseconds(1348203320000);
I need to do this in SQL server. I found some script here, but this was taking initial ticks from 1900-01-01.
I have used the DATEADD function as below, but this was giving an arithmetic overflow exception by supping milliseconds as difference:
SELECT DATEADD(MILLISECOND,1348203320000,'1970-1-1')
How can I do the conversion properly?
DECLARE #UTC BIGINT
SET #UTC = 1348203320997
SELECT DATEADD(MILLISECOND, #UTC % 1000, DATEADD(SECOND, #UTC / 1000, '19700101'))
Below the function that converts milliseconds to datetime
IF object_id('dbo.toDbTimeMSC', 'FN') IS NOT NULL DROP FUNCTION dbo.toDbTimeMSC
GO
CREATE FUNCTION [dbo].[toDbTimeMSC] (#unixTimeMSC BIGINT) RETURNS DATETIME
BEGIN
RETURN DATEADD(MILLISECOND, #unixTimeMSC % 1000, DATEADD(SECOND, #unixTimeMSC / 1000, '19700101'))
END
GO
-- select dbo.toDbTimeMSC(1348203320000)
I had problems with using answers given here (especially that the system was counting ticks form 0001-01-01) - so I did this:
CONVERT(DATETIME,[Time]/ 10000.0/1000/86400-693595)
--explanation for [Time_in_Ticks]/ 10000.0/1000/86400-693595
--Time is in "ticks"
--10000 = number of ticks in Milisecond
--1000 = number of milisecons in second
--86400 = number of seconds in a day (24hours*60minutes*60second)
--693595= number of days between 0001-01-01 and 1900-01-01 (which is base
-- date when converting from int to datetime)
Using SQL Server 2008R2 this produced the required result:
CAST(SWITCHOFFSET(CAST(dateadd(s, convert(bigint, [t_stamp]) / 1000, convert(datetime, '1-1-1970 00:00:00')) AS DATETIMEOFFSET), DATENAME (TZoffset, SYSDATETIMEOFFSET())) AS DATETIME)
The DATEADD requires an integer as a second argument. Your number 1348203320000 is very large for integer therefore it produce an error in runtime. Your should use bigint type instead and provide DATEADD with correct int values by splitting your milliseconds to seconds and milliseconds. That is sample you could use.
DECLARE #total bigint = 1348203320000;
DECLARE #seconds int = #total / 1000
DECLARE #milliseconds int = #total % 1000;
DECLARE #result datetime = '1970-1-1';
SET #result = DATEADD(SECOND, #seconds,#result);
SET #result = DATEADD(MILLISECOND, #milliseconds,#result);
SELECT #result
Right now, you can use dateadd with division on minutes and not seconds.
The code will be like this:
DATEADD(MILLISECOND, epoch% 60000, DATEADD(MINUTE, epoch/ 60000, '19700101'));
=dateadd("d",INT((Fields!lastLogon.Value / 864000000000)- 134774),"1970-01-01 00:00:00")
That's what I used in SSRS to get around the INT error, use days instead of seconds. Is it wrong?
Related
Looking for the most efficient and elegant way to do truncate the time to the minute
-- I need to truncate the time to the minute,
-- this code almost works but rounds up
SELECT
CAST('2021-09-02T15:15:30.9233333' AS datetime2(7)) AS EventDatetime2,
CAST(CAST('2021-09-02T15:15:30.9233333' AS datetime2(7)) AS TIME(0)) AS EventTime
As Larnu posted, if you want to round up or down depending on the seconds value, a simple convert to smalldatetime will do.
If you want to truncate, there are several ways, the simplest is probably just to add minutes to midnight (only posting because I prefer without the magic dates like 1900-01-01):
DECLARE #dt datetime2(7) = '2021-09-02T15:15:30.9233333';
DECLARE #d datetime2(7) = CONVERT(date, #dt);
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, #d, #dt), #d);
Another way is more intuitive but a little ugly:
DECLARE #dt datetime2(7) = '2021-09-02T15:15:30.9233333';
SELECT SMALLDATETIMEFROMPARTS
(
DATEPART(YEAR, #dt),
DATEPART(MONTH, #dt),
DATEPART(DAY, #dt),
DATEPART(HOUR, #dt),
DATEPART(MINUTE, #dt)
);
If you want to "round" to the nearest minute you could just CONVERT the value to a smalldatetime; they are only accurate to 1 minute:
SELECT CONVERT(smalldatetime,CONVERT(datetime2,'2021-09-02T15:15:30.9233333'));
If you want to, you can then CONVERT back to your original data type.
If you want to truncate (so strip the minutes) you could use the old DATEDIFF and DATEADD method:
DECLARE #DateTime2 datetime2(7) = '2021-09-02T15:15:30.9233333';
SELECT DATEADD(MINUTE,DATEDIFF(MINUTE,'19000101',#DateTime2),CONVERT(datetime2(7),'19000101'));
Just another option using left() and the implicit conversion.
Depending on the actual USE CASE, the outer convert() is optional
Example
DECLARE #dt datetime2(7) = '2021-09-02T15:15:30.9233333';
select convert(smalldatetime,left(#dt,16))
Results
2021-09-02 15:15:00
Combining the DATEADD and CAST(... AS SMALLDATETIME) approaches effectively gives you a minute "floor", like so:
SELECT CAST('2021-09-02T15:15:30.9233333' AS DATETIME2(7)) AS EventDatetime2,
CAST(CAST('2021-09-02T15:15:30.9233333' AS DATETIME2(7)) AS TIME(0)) AS EventTime,
CAST(CAST(DATEADD(
SECOND,
(DATEPART(SECOND, CAST('2021-09-02T15:15:30.9233333' AS DATETIME2(7))) * -1),
CAST('2021-09-02T15:15:30.9233333' AS DATETIME2(7))) AS SMALLDATETIME) AS TIME(0));
EventDatetime2
EventTime
(No column name)
2021-09-02 15:15:30.9233333
15:15:31
15:15:00
The DATEADD in this example subtracts the number of seconds from the datetime before converting it to a smalldatetime, so when that cast/convert does its rounding it will always go to the lower minute.
If, however, your input value is the sort of string literal that the wording of your question implies, you could also do this:
SELECT CAST(SUBSTRING('2021-09-02T15:15:30.9233333', CHARINDEX('T', '2021-09-02T15:15:30.9233333')+1, 6) + '00' AS TIME(0));
and get this result:
15:15:00
I have made a function in SQL to calculate the Age from the Birthday and it is like this:
FUNCTION [dbo].[GetAge] (#birthday datetime, #date datetime)
RETURNS int
AS
BEGIN
return datediff(SECOND, #birthday, #date) / (365.23076923074 * 24 * 60 * 60)
END
The birthday is of format : 1963-01-01 00:00:00.000
My problem is that when I call the function like this :
SELECT dbo.GetAge(birthday, '2014-12-17 00:00:00')
FROM [dbo].[Users]
GO
it says:
Msg 535, Level 16, State 0, Line 3
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.
BUT I call the same function with a date like :
SELECT dbo.GetAge(birthday, '1963-01-01 00:00:00')
FROM [dbo].[Users]
GO
I get the results..
So I don't understand what is the problem.
Pls help me and thank you in advance
The error says it all. "Try to use datediff with a less precise datepart"
return DATEDIFF(DAY, '1963-01-01 00:00:00', '2014-12-17 00:00:00') / (365.23076923074)
Seems obvious..the number of seconds from a user's birthday to today is too many for whatever datatype MySQL uses for DATEDIFF. But it's not too many from 1/1/1963.
Change your function to use a less precise datepart, i.e. minute instead of second.
FUNCTION [dbo].[GetAge] (#birthday datetime, #date datetime)
RETURNS int
AS
BEGIN
return datediff(MINUTE, #birthday, #date) / (365.23076923074 * 24 * 60)
END
OR hour
FUNCTION [dbo].[GetAge] (#birthday datetime, #date datetime)
RETURNS int
AS
BEGIN
return datediff(HOUR, #birthday, #date) / (365.23076923074 * 24)
END
OR DAY
FUNCTION [dbo].[GetAge] (#birthday datetime, #date datetime)
RETURNS int
AS
BEGIN
return datediff(DAY, #birthday, #date) / (365.23076923074)
END
Why not just DATEDIFF(year, #birthday, #date)? You only want the whole number of years, right?
Try casting your birthday to a date before sending it off.
SELECT dbo.GetAge(birthday, select cast('1963-01-01 00:00:00.000' as date))
FROM [dbo].[Users]
GO
I have a 'datetime' column with value 2013-03-22 15:19:02.000
I need to convert this value into epoch time and store it in a 'bigint' field
The actual epoch value for the above time is, 1363945741898, when I use
select DATEDIFF(s, '1970-01-01 00:00:00', '2013-03-22 15:19:02.000')
I get, 1363965542, when I use
select DATEDIFF(ms, '1970-01-01 00:00:00', '2013-03-22 15:19:02.000')
I get,
Msg 535, Level 16, State 0, Line 1
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.
How to get the exact epoch value from the 'datetime' field
I use SQL Server 2008. Also this should work with 2005.
Here is an example, not tested, written from free hand :)
declare #v_Date datetime
set #v_Date = '2013-03-22 15:19:02.000'
declare #v_DiffInSeconds integer
declare #v_DiffInMSeconds bigint
select #v_DiffInSeconds = DATEDIFF(s, '1970-01-01 00:00:00', #v_Date)
select #v_DiffInMSeconds = cast(#v_DiffInSeconds as bigint) * 1000 + cast(DATEPART(ms, #v_Date) as bigint)
Edit
I have made this example below to illustrate the time zone conversion. The given time stamp (in seconds where I have removed the last three digits "898") is here converted to the local IST time zone by adding the 5.5 hours (19800 seconds) and I convert it back to the time stamp from local time to GMT again. Below calculations matches the values in the question (in seconds).
declare #v_time datetime
set #v_time = '1970-01-01 00:00:00'
declare #v_date datetime
set #v_date = '2013-03-22 15:19:01'
-- This returns "March, 22 2013 15:19:01"
select dateadd(s, (1363945741 + 19800), #v_time)
-- This returns "1363945741"
select datediff(s, #v_time, #v_date) - 19800
When tried to get exact milliseconds we get the overflow exception. we can get the values till seconds and multiply with 1000.
This is equivalent to new Date().getTime() in javascript:
Use the below statement to get the time in seconds.
SELECT cast(DATEDIFF(s, '1970-01-01 00:00:00.000', '2016-12-09 16:22:17.897' ) as bigint)
Use the below statement to get the time in milliseconds.
SELECT cast(DATEDIFF(s, '1970-01-01 00:00:00.000', '2016-12-09 16:22:17.897' ) as bigint) * 1000
convert epoch to human readable date time using below statement:
select DATEADD(s, 1481300537, '1970-01-01 00:00:00')
Epoch to datetime
create function [dbo].[EpochToDate](#Date bigint)
returns datetime
begin
return (select dateadd(s, #Date, '19700101'))
end
Use below code to get human readable date from epoch time
select DATEADD(s,convert(bigint,#date)/2, DATEADD(s, convert(bigint,#date)/2, '1970-01-01 00:00:00'))
Could use guru help on this one. Trying to calculate the time between two datetime values and show as time in a T-SQL query...
SELECT arrivalDate - departDate AS timeToComplete
This should always be less than 24 hours. But who knows what the user may actually input?
I have been trying something like this with no resutls.
SELECT
CAST(time(7),
CONVERT(datetime, arrivalDate - departDate) AS timeToComplete) AS newTime,
Instead of showing results as 1:23:41 as an example, is there a way to show results like:
0D, 1H, 23M, 33S.
Thanks for any guidance on this.
You could get the total difference in seconds and then keep taking the largest part out of that. I.e., start with Days, then hours, minutes and seconds.
DECLARE #arrivalDate DATETIME = '2013-01-19 23:59:59'
DECLARE #departDate DATETIME = '2013-01-25 11:52:30'
DECLARE #SecondsDifference INT = DATEDIFF(SECOND, #arrivalDate, #departDate)
DECLARE #DayDifference INT = #SecondsDifference / 86400
DECLARE #HourDifference INT = (#SecondsDifference - (#DayDifference * 86400)) / 3600
DECLARE #MinDifference INT = (#SecondsDifference - (#DayDifference * 86400) - (#HourDifference * 3600)) / 60
DECLARE #SecDifference INT = (#SecondsDifference - (#DayDifference * 86400) - (#HourDifference * 3600) - (#MinDifference * 60))
I've done it here using variables for clarity, but you could work this into a single query. DATEDIFF wont work for the smaller chunks of the difference until you remove the larger ones because you'd get the totals. For example:
DATEDIFF(HOUR, #arrivalDate, #departDate)
would return the total number of hours, not the hours less the whole days.
Just to be different :)
Try to use this approach:
declare #date1 datetime;
declare #date2 datetime;
set #date1 = '2012-05-01 12:00:000'
set #date2 = '2012-05-01 18:00:000'
SELECT
STUFF(
STUFF(
STUFF(
RIGHT(CONVERT(NVARCHAR(19), CONVERT(DATETIME, DATEADD(second, DATEDIFF(S, #date1, #date2), '20000101')), 120), 11),
3, 1, 'D, '),
8, 1, 'H, '),
13, 1, 'M, ') + ' S';
Finally found a great solution at this link,
SQL - Seconds to Day, Hour, Minute, Second
thanks for the help though folks, it got me further into this issue and searching for the right info.
I'm using the Between command in SQL Server.
I need to find :
select * from MyTable where myDate
between getdate() and [1ms before tomorrow = 2012-02-26 :23:59:59:999]
I DON'T want [ 2012-02-27 :00:00:00:000] because future queries should use that value .
So I need 1 ms before tomorrow.
However - this is what I've tried but for some reason it refuse to give me the desire value !
and give me : 2012-02-26 23:59:59.997 + unpredictable results!
Why is that ? What am I missing ?
I want to get 2012-02-26 :23:59:59:999 !
Why not specify an exclusive range instead?
SELECT * FROM `MyTable`
WHERE `myDate` >= GETDATE() AND `myDate` < (tomorrow)
(I can't be bothered to figure out how to get tomorrow's DATETIME as I'm usually a MySQL guy, but I believe you already know how to do it.)
Otherwise you're stuck messing around with floating-point values of questionable accuracy.
The SQL Server DATETIME has an accuracy of 3.33ms - you'll always get the .997 as the closest value to a full hour. That's just the way it is, and you cannot change it in SQL Server 2005. Read all about it at Demystifying the SQL Server DATETIME datatype.
In SQL Server 2008, you can use the DATETIME2 datatype which has an accuracy of 100ns - so there you have up to 7 exact digits after the "seconds" decimal point.
Update: if you want to get .999 with a DATETIME2, you need to use:
DECLARE #dt2 DATETIME2
-- you need to cast GETDATE() to DATETIME2 - otherwise it's a DATETIME !
SET #dt2 = CAST(GETDATE() AS DATETIME2)
DECLARE #dt2_Added DATETIME2
SET #dt2_Added = DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0)
SELECT DATEADD(ms, -1, #dt2_added)
Result:
2012-02-26 23:59:59.9990000
Update #2: things get stranger still.....
If I use SYSDATETIME() instead of GETDATE(), it gives me a DATETIME2 right from the get to - but if I do the calculation in one step:
DECLARE #dt2 DATETIME2
SET #dt2 = SYSDATETIME()
SELECT DATEADD(ms, -1, DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0) )
I get the result of :
2012-02-27 00:00:00.000
but if I do the same calculation in two steps:
DECLARE #dt2 DATETIME2
SET #dt2 = SYSDATETIME()
DECLARE #dt2_Added DATETIME2
SET #dt2_Added = DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0)
SELECT DATEADD(ms, -1, #dt2_added)
I get the expected result:
2012-02-26 23:59:59.9990000
This is indeed quite weird......