T-SQL formatting calculated column as time - sql-server

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.

Related

converting int to hh:mm format

I have separate integers for hours and minutes and i need to find a way to get the total number of hours followed by minutes preferably in a HH:MM format. The issue that i'm facing is when the minutes are less than ten there is no leading zero and i am doing this for reporting reasons and so would love to be able to do something like
Total Hours worked
102:06 to represent 102 hours and 6 minutes
DECLARE #hours INT = 102
declare #minutes int = 6
SELECT
CONCAT(CAST (SUM((#hours*60)+#minutes)/60 AS VARCHAR(5)) , ':' , CAST (SUM((#hours*60)+#minutes)%60 AS VARCHAR(2)))
In SQL Server, you can do:
select concat(hours, ':',
right('00' + minutes, 2)
)
Another method would be:
select concat(hours, ':',
right(convert(varchar(255), 100 + minutes), 2)
)
Just another similar option using format()
Example
DECLARE #hours INT = 102
declare #minutes int = 6
Select concat(#hours,format(#minutes,':00'))
Returns
102:06

Time difference with hours, minutes and seconds in SQL Server

I need to find time difference between two columns with hours, minutes and seconds.
These are two datetime columns in my table:
STOP_TIME Start_Time
------------------------------------------------------
2016-05-10 03:31:00.000 2016-05-10 02:25:34.000
I calculated second difference for stoptime and starttime. 3926 is the second difference.
I need to convert this to time format hh:mm:ss.
This should work for you -
DECLARE #STOP_TIME DATETIME = '2016-05-10 03:31:00.000',
#Start_Time DATETIME = '2016-05-10 02:25:34.000'
SELECT
RIGHT('0' + CAST(DATEDIFF(S, #Start_Time, #STOP_TIME) / 3600 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, #Start_Time, #STOP_TIME) % 3600/60 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, #Start_Time, #STOP_TIME) % 60 AS VARCHAR(2)),2)
Sql server supports adding and subtracting on Datetime data type, so you can simply do something like this:
DECLARE #StartTime datetime = '2016-05-10 02:25:34.000',
#EndTime datetime = '2016-05-10 03:31:00.000'
SELECT CAST(#EndTime - #StartTime as Time) As TimeDifference
Result: 01:05:26
Note: As TT rightfully wrote in his comment, casting to time will only work if the difference between #EndTime and #StartTime is less then 24 hours.
If you need to compare times that are further apart, you need to use one of the other solutions suggested.

How to calculate time difference in T-SQL

I have created a table with columns of datatype time(7)
I want to calculate the time difference between them.
Table time:
id timefrom timeto result
--------------------------------------
1 13:50:00 14:10:00 00:20:00
2 11:10:00 11:00:00 23:50:00
For example:
Time From 13:50
Time To 14:10
Result should show 00:20.
Is there a function for this?
DATEDIFF(hour, UseTimeFrom, UseTimeTo) hourtime,
(DATEDIFF(MINUTE, UseTimeFrom , UseTimeTo)) - (((DATEDIFF(hour, UseTimeFrom, UseTimeTo)) * 60)) as mintime
You can do it this way:
select *, convert(time, convert(datetime, timeto) - convert(datetime, timefrom))
from table1
This will convert the times to datetime for day 0 (1.1.1900) and then do the calculation and in case the timeto is smaller it will get to previous day, but convert to time will get the time part from it.
Example in SQL Fiddle
There's no built-in function - but you could relatively easily write your own T-SQL stored function to calculate this - something like this:
CREATE FUNCTION dbo.TimeDifference (#FromTime TIME(7), #ToTime TIME(7))
RETURNS VARCHAR(10)
AS BEGIN
DECLARE #Diff INT = DATEDIFF(SECOND, #FromTime, #ToTime)
DECLARE #DiffHours INT = #Diff / 3600;
DECLARE #DiffMinutes INT = (#Diff % 3600) / 60;
DECLARE #DiffSeconds INT = ((#Diff % 3600) % 60);
DECLARE #ResultString VARCHAR(10)
SET #ResultString = RIGHT('00' + CAST(#DiffHours AS VARCHAR(2)), 2) + ':' +
RIGHT('00' + CAST(#DiffMinutes AS VARCHAR(2)), 2) + ':' +
RIGHT('00' + CAST(#DiffSeconds AS VARCHAR(2)), 2)
RETURN #ResultString
END
This function uses the integer division (/) and integer remainder (%) operators to calculate the number of hours, minutes and seconds that those two times are apart, and then concatenates those together into a string as you are looking for.
SELECT
dbo.TimeDifference('13:50:00', '14:10:00'),
dbo.TimeDifference('13:50:00', '15:51:05'),
dbo.TimeDifference('13:50:00', '15:35:45')
Sample output:
00:20:00 02:01:05 01:45:45

Convert UTC Milliseconds to DATETIME in SQL server

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?

In TSQL, how would you convert from an int to a datetime and give the age?

What would be the sql for the following,
I have a date of birth in an int field,
ie YYYYMMDD = 19600518
I would like to get the age.
None of the other answers are actually calculating age. They're calculating the number of year boundaries and not taking the birthday into account.
To calculate the age, you'll need to do something like this:
DECLARE #d DATETIME
SET #d = CONVERT(DATETIME, CONVERT(VARCHAR(8), 19600518), 112)
SELECT DATEDIFF(year, #d, GETDATE())
- CASE WHEN DATEADD(year, DATEDIFF(year, #d, GETDATE()), #d) <= GETDATE()
THEN 0 ELSE 1 END AS Age
Most of the other answers are not calculating age - just whole years (e.g. Jan 1 2009 is one "year" after Dec 31 2008). Thus, if you use most of the calculations on this page, you will return an incorrect age for half of the year, on average. Luke is the only person who has seen this but his answer strikes me as too complicated - there is an easier way:
Select CAST(DATEDIFF(hh, [birthdate], GETDATE()) / 8766 AS int) AS Age
(NOTE: Thanks go to 'Learning' for making a great catch on my original algorithm - this is a revision that uses hours instead of days)
Because the rounding here is very granular, this is almost perfectly accurate for every day of every year. The exceptions are so convoluted that they are almost humorous: every fourth year the age returned will be one year too young if we A) ask for the age before 6:00 AM, B) on the person's birthday and C) their birthday is after February 28th. Of course, depending on what time someone was born this might 'technically' be correct! In my setting, this is a perfectly acceptable compromise.
Here is a loop that prints out ages to show that this works.
Declare #age int;
Declare #BirthDate datetime;
Declare #Year int;
Set #Year = 2008;
WHILE (#Year > 1930)
BEGIN
-- Put today's date where you see '-03-18'
SET #BirthDate = CAST(Cast(#Year as varchar(4)) + '-03-18' AS DATETIME)
SELECT #age=CAST(DATEDIFF(hh, #BirthDate, GETDATE()) / 8766 AS int);
Print Cast(#Year as varchar) + ' Age: ' + Cast(#age as varchar);
Set #Year = #Year - 1;
END;
Finally, this is the version that will also convert Paul's integer date to a real date:
CAST(DATEDIFF(hh, Convert(Datetime, Convert(varchar(8), [birthdate]), 112), GETDATE()) / 8766 AS int) AS Age
DECLARE #dateSt VARCHAR(8)
DECLARE #startDt DATETIME
-- Set the start date string
SET #dateSt = '19600518'
-- Make it a DATETIME (the ISO way)
SET #startDt = CAST(SUBSTRING(#dateSt, 1, 4) + '-' +
SUBSTRING(#dateSt, 5, 2) + '-' +
SUBSTRING(#dateSt, 7, 2) AS DATETIME)
-- Age in Days
SELECT DATEDIFF(D, #startDt, getdate())
Age in years :
select datediff(YY, convert(datetime, convert(varchar, 19600518)), getdate())
[EDIT]
-- I forgot to declare the variables
declare #birthday datetime;
set #birthday = convert(datetime,convert(varchar, 19600518), 112);
declare #datetoday datetime;
set #datetoday = getdate();
select
(
CASE
WHEN dateadd(year, datediff (year, #birthday, #datetoday), #birthday) <= #datetoday
THEN datediff (year, #birthday, #datetoday)
ELSE datediff (year, #birthday, #datetoday) - 1
END) as age;
Here's a one-liner way to do it:
CONVERT(DATETIME, CONVERT(VARCHAR(8),19600518), 112)
But beware! This relies on T-SQL, and probably won't work in other SQL environments.
Please note that the "style" of 112 is simply the "ISO" date format of yyyymmdd. (Something I found in some CONVERT documentation.)
This is a reason why you should NOT ever store dates as anything except a datetime datatype. The best fix is to change your datatype and convert all the dates once (wouldn't be surprised if there are few invalid ones in there either). then you never have to do these workarounds again.
I worked it out and got same as #Learning
select dob, datediff(year, convert(datetime, convert(varchar(8),[dob])) ,getdate()) as age
from [mytable]
where IsDate(convert(varchar(8),[dob])) = 1
NB. I needed the IsDate as well as there were some invalid dates in the data.
Edit. Here is an article from SQLServerCentral on calculating age.

Resources