I want Hours,Min, second difference from two datetime - sql

I am developing Time management system for employees.
I want the duration how much duration employee come late , or he went early.
i have following structure.
**Attendace**
AutoId --uniqueidentifier
EMployeeId --uniqueidentifier
Date --datetime
InTime -- varchar(50)
OutTime -- varchar(50)
ActualInTime--datetime
ActualOutTime--datetime
I want Late Coming Report ( i.e. who came late in morning after ActualInTime and how much duration in hh:mm:ss ) and also want early going(i.e who went early in the evening before ActualOutTime in duration in format hh:mm:ss )
So can you please help me..???

I came across an easier way of solving this issue.
First, a quick example of turning a "number of seconds" into the "hh:mm:ss" format.
DECLARE #NumberOfSeconds int
SET #NumberOfSeconds = 3843 -- 1 hour, 4 minutes, 3 seconds
SELECT #NumberOfSeconds AS 'seconds',
CONVERT(varchar, DATEADD(second, #NumberOfSeconds, 0), 108) AS 'hh:mm:ss'
This will give us this output:
And we can easily take this a step further, calculate the number of seconds between two datetimes, and display it in hh:mm:ss format:
DECLARE
#NumberOfSeconds int,
#StartTime datetime = '2017-09-14 14:16:11',
#EndTime datetime = '2017-09-14 14:23:13'
SET #NumberOfSeconds = DATEDIFF(second, #StartTime, #EndTime)
SELECT #NumberOfSeconds AS 'seconds',
CONVERT(varchar, DATEADD(second, #NumberOfSeconds, 0), 108) AS 'hh:mm:ss'
Which gives us this output:
Simple, hey ?
(And yes, you can simplify it further by putting the DATEDIFF directly into the DATEADD function.)

You can do it in a very simple way:
declare #date1 datetime, #date2 datetime
set #date1=DATEADD(s,-638,getdate())
set #date2=GETDATE()
select convert(char(8),dateadd(s,datediff(s,#date1,#date2),'1900-1-1'),8)
... the result is 00:10:38 (638s = 600s + 38s = 10 minutes and 38 seconds)
Another example:
select distinct convert(char(8),dateadd(s,datediff(s, CRDATE , GETDATE() ),'1900-1-1'),8) from sysobjects order by 1
It will works until the difference of 86399 seconds (23:59:59):
select convert(char(8),dateadd(s,datediff(s
, DATEADD(s,-86399,GETDATE())
, GETDATE()
),'1900-1-1'),8)
... after that it will return to zero:
select convert(char(8),dateadd(s,datediff(s
, DATEADD(s,-86400,GETDATE())
, GETDATE()
),'1900-1-1'),8)

Because they are the same day (you don't have to worry about number of hours >24), you can just use a combination of DATEDIFF(second,time1,time2) and DATEADD(second,0,) to get a datetime value.
To format to hh:nn:ss, use convert(char(8),answer,8) but this is something better done by the reporting front end against the datetime result.
-- Late report
select *, dateadd(s,0,datediff(s,intime,actualintime)) late_by
from attendance
where intime < actualintime

this code might help you...
DECLARE #First datetime
DECLARE #Second datetime
SET #First = '04/02/2008 05:23:22'
SET #Second = getdate()
SELECT DATEDIFF(day,#First,#Second)*24 as TotalHours,
DATEDIFF(day,#First,#Second)*24*60 as TotalMinutes,
DATEDIFF(day,#First,#Second)*24*60*60 as TotalSeconds

well, yes, you need to use DATEDIFF, and yes, all that posted above works, but, if you want to show 07:07:07 instead of 7:7:7, you have to do something like this:
Declare #starttime datetime, #endtime datetime, #seconds int, #minutes int, #hours int
Set #starttime ='2013-10-01 05:05:17'
Set #endtime = '2013-10-01 23:10:18'
set #hours = DateDiff(hour, #starttime, #endtime)
set #minutes = DateDiff(minute, #starttime, #endtime);
set #seconds = DateDiff(second, #starttime, #endtime);
select case when DateDiff(minute, #starttime, #endtime) > 60
then CASE WHEN #hours >= 10 THEN cast(#hours as varchar(3))
ELSE '0' + cast(#hours as varchar(3)) END +':' +
CASE WHEN #minutes - (#hours * 60) >= 10 THEN
cast((#minutes - (#hours * 60)) as varchar(3))
ELSE '0' +cast((#minutes - (#hours * 60)) as varchar(3)) END
+ CASE WHEN (#seconds - (#minutes *60)) >= 10 THEN
+':' + cast(#seconds - (#minutes *60) as varchar(10))
ELSE ':0' + cast(#seconds - (#minutes *60) as varchar(10)) END
ELSE '0' + cast(#minutes as varchar(3)) +':' + cast(#seconds as varchar(10))
end
It may not look very nice, but it gave me what i wanted.

How about using CAST.
,CAST (Table1.DateTimeLatest-Table1.DateTimeFirst as time) as [Elapsed Time]
The raw result from SSMS from an apparatus table:
SQL Return shows out to nanoseconds in this Data.
For the report, as pasted in formatted Excel sheet:
Formatted result column as hh:mm:ss.

SELECT id, pickupdateandtime, GETDATE() AS CurrentTime,
((DATEDIFF(day,GETDATE(),pickupdateandtime)) - 1) AS Days ,
convert(char(8),dateadd(s,datediff(s,GETDATE(),pickupdateandtime),'1900-1-
1'),8) AS 'Hours & Mins' FROM orders
Here's what worked for me. Thank you #lynx_74.
https://i.stack.imgur.com/hOmyJ.png

Create a stored procedure to do the work and then just call the procedure passing your start and end dates.
CREATE PROCEDURE [dbo].[GetOperationDuration]
#DurationStart DATETIME, #DurationEnd DATETIME,
#Duration VARCHAR(100) OUTPUT
AS
BEGIN
DECLARE #years INT, #months INT, #days INT,
#hours INT, #minutes INT, #seconds INT, #milliseconds INT;
-- DOES NOT ACCOUNT FOR LEAP YEARS
SELECT #years = DATEDIFF(yy, #DurationStart, #DurationEnd)
IF DATEADD(yy, -#years, #DurationEnd) < #DurationStart
SELECT #years = #years-1
SET #DurationEnd = DATEADD(yy, -#years, #DurationEnd)
SELECT #months = DATEDIFF(mm, #DurationStart, #DurationEnd)
IF DATEADD(mm, -#months, #DurationEnd) < #DurationStart
SELECT #months=#months-1
SET #DurationEnd= DATEADD(mm, -#months, #DurationEnd)
SELECT #days=DATEDIFF(dd, #DurationStart, #DurationEnd)
IF DATEADD(dd, -#days, #DurationEnd) < #DurationStart
SELECT #days=#days-1
SET #DurationEnd= DATEADD(dd, -#days, #DurationEnd)
SELECT #hours=DATEDIFF(hh, #DurationStart, #DurationEnd)
IF DATEADD(hh, -#hours, #DurationEnd) < #DurationStart
SELECT #hours=#hours-1
SET #DurationEnd= DATEADD(hh, -#hours, #DurationEnd)
SELECT #minutes=DATEDIFF(mi, #DurationStart, #DurationEnd)
IF DATEADD(mi, -#minutes, #DurationEnd) < #DurationStart
SELECT #minutes=#minutes-1
SET #DurationEnd= DATEADD(mi, -#minutes, #DurationEnd)
SELECT #seconds=DATEDIFF(s, #DurationStart, #DurationEnd)
IF DATEADD(s, -#seconds, #DurationEnd) < #DurationStart
SELECT #seconds=#seconds-1
SET #DurationEnd= DATEADD(s, -#seconds, #DurationEnd)
SELECT #milliseconds=DATEDIFF(ms, #DurationStart, #DurationEnd)
SELECT #Duration= ISNULL(CAST(NULLIF(#years,0) AS VARCHAR(10)) + ' years,','')
+ ISNULL(' ' + CAST(NULLIF(#months,0) AS VARCHAR(10)) + ' months,','')
+ ISNULL(' ' + CAST(NULLIF(#days,0) AS VARCHAR(10)) + ' days,','')
+ ISNULL(' ' + CAST(NULLIF(#hours,0) AS VARCHAR(10)) + ' hours,','')
+ ISNULL(' ' + CAST(#minutes AS VARCHAR(10)) + ' minutes and','')
+ ISNULL(' ' + CAST(#seconds AS VARCHAR(10))
-- UNCOMMENT THEFOLLOWING IF YOU WANT MILLISECONDS INCLUDED
--+ CASE
--WHEN #milliseconds > 0
--THEN '.' + CAST(#milliseconds AS VARCHAR(10))
--ELSE ''
--END
+ ' seconds','')
SELECT #Duration
END
GO
Then just call using:
DECLARE #return_value int, #Duration varchar(100)
EXEC #return_value = [dbo].[GetOperationDuration] #DurationStart, #DurationEnd, #Duration = #Duration OUTPUT
SELECT #Duration as N'#Duration'

Thought I'd share my 2 cents. This fixes the overflow problems but only works with datetime not datetime2. It probably does not work with leap years or when clocks go backwards/forwards. I haven't tested with either.
declare #startTime datetime = getdate()
declare #endTime datetime
select [StartDate] = #startTime,
[EndDate] = #endTime,
[DD:HH:MM:SS.MS] = right( '00' + convert( varchar(20), datediff(hh, 0, #endTime - #startTime ) / 24 ), 2) + ':' +
right( '00' + convert( varchar(20), datediff(hh, 0, #endTime - #startTime ) % 24 ), 2) + ':' +
substring( convert( varchar(20), #endtime - #startTime, 114 ),
charindex( ':', convert( varchar(20), #endTime - #startTime, 114 ) ) + 1,
len( convert( varchar(20), #endTime - #startTime, 114 ) ) )

Related

Calculate age on integer field

The date field I have to calculate age on is yyyymmdd.
I've tried below and converted getdate to yyyymmdd format but can't seem to get the age from that. I've tried with datediff but can't seem to get it to work either.
SELECT CLAIM.BTHDAT
, (CONVERT(VARCHAR(8),GETDATE(), 112) - CLAIM.BTHDAT)/365.25
FROM CLAIM
Assuming you want AGE in YEARS... How about datediff()
Select Age = datediff(YEAR,left(CLAIM.BTHDAT,8),getdate())
From CLAIM
try this....
SELECT CLAIM.BTHDAT, DATEDIFF(hour,CLAIM.BTHDAT,GETDATE())/8766.0 AS AgeYearsDecimal
,CONVERT(int,ROUND(DATEDIFF(hour,CLAIM.BTHDAT,GETDATE())/8766.0,0)) AS AgeYearsIntRound
,DATEDIFF(hour,CLAIM.BTHDAT,GETDATE())/8766 AS AgeYearsIntTrunc FROM CLAIM
If you want to Age in Day,Month & year then you can try this.Create Function to Calcuate Age and call it in Query like this
Create function [dbo].[GetAge](#dayOfBirth datetime, #today datetime)
RETURNS varchar(100)
AS
Begin
DECLARE #tmpdate datetime, #date datetime, #years int, #months int, #days int
SELECT #tmpdate = #dayOfBirth
SELECT #years = DATEDIFF(yy, #tmpdate, #today) - CASE WHEN (MONTH(#tmpdate) > MONTH(#today)) OR (MONTH(#tmpdate) = MONTH(#today) AND DAY(#tmpdate) > DAY(#today)) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate)
SELECT #months = DATEDIFF(m, #tmpdate, #today) - CASE WHEN DAY(#tmpdate) > DAY(#today) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(m, #months, #tmpdate)
SELECT #days = DATEDIFF(d, #tmpdate, #today)
return cast(#years as varchar(2)) + ' years,' + cast(#months as varchar(2)) + ' months,' + cast(#days as varchar(3)) + ' days'
end
Select CLAIM.BTHDAT,dbo.[GetAge](CLAIM.BTHDAT,getdate()) From CLAIM
Here's an option to get the age accurately, with the assumption that all dates will follow the yyyymmdd format and will be valid dates.
SELECT CLAIM.BTHDAT
,DATEDIFF( YY, CONVERT(CHAR(8),CLAIM.BTHDAT), GETDATE())
- CASE WHEN SUBSTRING( CONVERT( char(8), GETDATE(), 112), 5, 4) < SUBSTRING( CONVERT( char(8), BTHDAT), 5, 4) THEN 1 ELSE 0 END
FROM CLAIM

SQL get time values between a time range

I have to calculate all the time values which are between a particular start time and end time on the basis of a particular time interval on a date in stored procedure in SQL.
I have 4 parameters for my stored procedure.
#date_value nvarchar(1000),//date value'2016-10-09'
#starttime TIME(0) //= '08:00',//suppose starttime is 8am
#endtime TIME(0) //= '13:00'
#interval INT //= '20' //20 minutes
I am trying to get all the time values between the starttime and endtime. I need it like this.
8:00,8:20,08:40........upto 12:50(end value I dont need).
I have googled it and found that we can use
SELECT DATEADD(MINUTE, #MinutesToAdd, #StartTime)
Here I am not able to include the end time.Please help me
Declare
#date_value nvarchar(1000)='2016-10-09',
#starttime TIME(0)= '08:00',
#endtime TIME(0) = '13:00',
#interval INT = '20'
;With cte(stime)
as
(
SELECT
cast(cast( #date_value as datetime)
+ CONVERT(CHAR(8), #starttime, 108) as time)
union all
select
cast(dateadd(minute,#interval,stime) as time)
from cte
where cast(dateadd(minute,#interval,stime) as time)<#endtime
)
select * from cte
Here is one way without LOOP or Recursion
;with cte as
(
SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n as seq
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n)
),time_gen as
(
SELECT Dateadd(MINUTE, #interval * seq , Cast(Concat(#date_value, ' ', #starttime) AS DATETIME)) as dates
FROM cte
)
select cast(dates as time) times from time_gen
WHERE dates < Cast(Concat(#date_value, ' ', #endtime) AS DATETIME)
order by times
Note : If you not using SQL SERVER 2012+, then use + for concatenation instead of Concat function
DECLARE #date_value nvarchar(1000) = '2016-10-09'
DECLARE #starttime TIME(0) = '08:00'
DECLARE #endtime TIME(0) = '13:00'
DECLARE #interval INT = '20'
DECLARE #IterateTime AS TIME(0) = #starttime
DECLARE #Diff AS INT = (SELECT DATEDIFF(MINUTE, #starttime, #endtime)) / #interval
DECLARE #Iterator AS INT = 0
WHILE #Iterator < #Diff
BEGIN
SELECT #IterateTime = DATEADD(MINUTE, #interval, #IterateTime)
SELECT #Iterator = #Iterator + 1
SELECT #IterateTime
END

sql query to show average of each tag present in proficy historian

I need to develop ssrs report in which user will provide a month as varchar(2) and year as varchar(4). When a user clicks on a view report button, an ssrs report should display result as follows. (suppose if user pass month as 12 and year as 2013)
Date TagName Average
12/01/13 Tag01 45.23
12/01/13 Tag02 89.23
12/02/13 Tag01 2.363
12/02/13 Tag02 45.23
.
.
.
12/31/13 Tag01 55.24
12/31/13 Tag02 95.24
I designed the following query
CREATE TABLE #tempval
(
[timestamp] VARCHAR(30),
tagname VARCHAR(300),
tagval DECIMAL(18, 5)
)
DECLARE #month VARCHAR(2)
DECLARE #year VARCHAR(4)
SET #month='08'
SET #year='2014'
DECLARE #startdate VARCHAR(30)
DECLARE #enddate VARCHAR(30)
SET #startdate=#month + '/01/' + #year
IF ( CONVERT(INT, #month) >= Month(Getdate())
AND CONVERT(INT, #year) >= Year(Getdate()) )
BEGIN
SET #enddate=CONVERT(VARCHAR, (SELECT Getdate()))
END
ELSE
BEGIN
SET #enddate=CONVERT(VARCHAR, Dateadd(day, -1, Dateadd(month, 1, CONVERT(
DATETIME, #startdate
))
))
END
DECLARE #query VARCHAR(1000)
DECLARE #starttime VARCHAR(30)
DECLARE #endtime VARCHAR(30)
SET #starttime= CONVERT(VARCHAR, Datepart(month, Dateadd(hour, 22, Dateadd(day,
-1, CONVERT(
DATETIME, #startdate)))))
+ '/'
+ CONVERT(VARCHAR, Datepart(day, Dateadd(hour, 22, Dateadd(day,
-1, CONVERT(DATETIME, #startdate)))))
+ '/'
+ CONVERT(VARCHAR, Datepart(year, Dateadd(hour, 22, Dateadd(day,
-1, CONVERT(DATETIME, #startdate)))))
+ ' '
+ CONVERT(VARCHAR, Datepart(hour, Dateadd(hour, 22, Dateadd(day,
-1, CONVERT(DATETIME, #startdate)))))
+ ':'
+ CONVERT(VARCHAR, Datepart(minute, Dateadd(hour, 22, Dateadd(
day, -1, CONVERT(DATETIME, #startdate)))))
+ ':'
+ CONVERT(VARCHAR, Datepart(second, Dateadd(hour, 22, Dateadd(
day, -1, CONVERT(DATETIME, #startdate)))))
SET #endtime=CONVERT(VARCHAR, Datepart(month, Dateadd(hour, 22, CONVERT(DATETIME
, #startdate)
)))
+ '/'
+ CONVERT(VARCHAR, Datepart(day, Dateadd(hour, 22, CONVERT(DATETIME
, #startdate))))
+ '/'
+ CONVERT(VARCHAR, Datepart(year, Dateadd(hour, 22, CONVERT(
DATETIME, #startdate))))
+ ' '
+ CONVERT(VARCHAR, Datepart(hour, Dateadd(hour, 22, CONVERT(
DATETIME, #startdate))))
+ ':'
+ CONVERT(VARCHAR, Datepart(minute, Dateadd(hour, 22, CONVERT(
DATETIME, #startdate))))
+ ':'
+ CONVERT(VARCHAR, Datepart(second, Dateadd(hour, 22, CONVERT(
DATETIME, #startdate))))
SET #query='select * from openquery(muri,''set StartTime='''''
+ #starttime + ''''',EndTime=''''' + #endtime
+
''''' select * from ihrawdata where tagname=MURISERVER.MURI.DCS.ASSETS.87A.87A_FI_2101.DACA.PV and samplingmode=rawbytime'')'
EXEC (#query)
But it displays blank columns but I'm not sure why.
The easiest way I've found for an SSRS report to query GE Proficy Historian is to use dynamic SQL within a stored proc.
The prerequisite is that you have a SQL Server linked server configured using the IhOLEDB.iHistorian provider. That would look something like this once installed:
You then create a stored proc as normal, I usually have a fairly generic proc which takes most of the arguments you'd want to query a GE Historian with. Example stored proc definition:
CREATE PROCEDURE [utility].[Historian_GetData] #DateFrom DATETIME,
#DateTo DATETIME,
#TagList VARCHAR(1000),
#Historian NVARCHAR(100),
#SampleInterval NVARCHAR(50),
#SampleMethod NVARCHAR(50),
#DefaultRowCount INT = 5000
However to keep the example simple, here is an anonymous block with some dates which will be used to query. Essentially, for each of the parameters in the stored proc you'd add them to the dynamic SQL.
DECLARE #DateFrom NVARCHAR(100) = '2018-05-02 06:00'
DECLARE #DateTo NVARCHAR(100) = '2018-05-03 06:00'
DECLARE #SQL NVARCHAR(4000)
DECLARE #Result TABLE (TagName NVARCHAR(100) NOT NULL, [Timestamp] DATETIME NOT NULL, Value NVARCHAR(100) NOT NULL, Quality NVARCHAR(100) NOT NULL)
BEGIN
SET #SQL = 'SELECT tagname, timestamp, value, quality
FROM OPENQUERY ([Your-Historian],
''SET StartTime = "' + #DateFrom + '", EndTime = "' + #DateTo + '",
SamplingMode = RawByTime
SELECT tagname, timestamp, value, quality
FROM ihRawData
WHERE TagName = XYZ'')';
INSERT INTO #Result EXEC sp_executesql #SQL
SELECT TagName,
[Timestamp],
[Value],
Quality
FROM #Result ORDER BY TagName, [Timestamp]
END
The result for that will look something like this:
So in summary:
Configure your linked server to point to your Historian
Create your stored proc accepting all the Historian query arguments as parameters.
Execute your dynamic SQL
Calculate your result as required, in your case some averages.

Difference of two date time in sql server

Is there any way to take the difference between two datetime in sql server?
For example, my dates are
2010-01-22 15:29:55.090
2010-01-22 15:30:09.153
So, the result should be 14.063 seconds.
Just a caveat to add about DateDiff, it counts the number of times you pass the boundary you specify as your units, so is subject to problems if you are looking for a precise timespan.
e.g.
select datediff (m, '20100131', '20100201')
gives an answer of 1, because it crossed the boundary from January to February, so even though the span is 2 days, datediff would return a value of 1 - it crossed 1 date boundary.
select datediff(mi, '2010-01-22 15:29:55.090' , '2010-01-22 15:30:09.153')
Gives a value of 1, again, it passed the minute boundary once, so even though it is approx 14 seconds, it would be returned as a single minute when using Minutes as the units.
SELECT DATEDIFF (MyUnits, '2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')
Substitute "MyUnits" based on DATEDIFF on MSDN
SELECT DATEDIFF(day, '2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')
Replace day with other units you want to get the difference in, like second, minute etc.
I can mention four important functions of MS SQL Server that can be very useful:
1) The function DATEDIFF() is responsible to calculate differences between two dates, the result could be "year quarter month dayofyear day week hour minute second millisecond microsecond nanosecond", specified on the first parameter (datepart):
select datediff(day,'1997-10-07','2011-09-11')
2) You can use the function GETDATE() to get the actual time and calculate differences of some date and actual date:
select datediff(day,'1997-10-07', getdate() )
3) Another important function is DATEADD(), used to convert some value in datetime using the same datepart of the datediff, that you can add (with positive values) or substract (with negative values) to one base date:
select DATEADD(day, 45, getdate()) -- actual datetime adding 45 days
select DATEADD( s,-638, getdate()) -- actual datetime subtracting 10 minutes and 38 seconds
4) The function CONVERT() was made to format the date like you need, it is not parametric function, but you can use part of the result to format the result like you need:
select convert( char(8), getdate() , 8) -- part hh:mm:ss of actual datetime
select convert( varchar, getdate() , 112) -- yyyymmdd
select convert( char(10), getdate() , 20) -- yyyy-mm-dd limited by 10 characters
DATETIME cold be calculated in seconds and one interesting result mixing these four function is to show a formated difference um hours, minutes and seconds (hh:mm:ss) between two dates:
declare #date1 datetime, #date2 datetime
set #date1=DATEADD(s,-638,getdate())
set #date2=GETDATE()
select convert(char(8),dateadd(s,datediff(s,#date1,#date2),'1900-1-1'),8)
... the result is 00:10:38 (638s = 600s + 38s = 10 minutes and 38 seconds)
Another example:
select distinct convert(char(8),dateadd(s,datediff(s, CRDATE , GETDATE() ),'1900-1-1'),8) from sysobjects order by 1
I tried this way and it worked. I used SQL Server version 2016
SELECT DATEDIFF(MILLISECOND,'2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')/1000.00;
Different DATEDIFF Functions are:
SELECT DATEDIFF(year, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(quarter, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(month, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(dayofyear, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(day, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(hour, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(minute, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(second, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(millisecond, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
Ref: https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
Ok we all know the answer involves DATEDIFF(). But that gives you only half the result you may be after. What if you want to get the results in human-readable format, in terms of Minutes and Seconds between two DATETIME values?
The CONVERT(), DATEADD() and of course DATEDIFF() functions are perfect for a more easily readable result that your clients can use, instead of a number.
i.e.
CONVERT(varchar(5), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114)
This will give you something like:
HH:MM
If you want more precision, just increase the VARCHAR().
CONVERT(varchar(12), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114)
HH:MM.SS.MS
There are a number of ways to look at a date difference, and more when comparing date/times. Here's what I use to get the difference between two dates formatted as "HH:MM:SS":
ElapsedTime AS
RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
I used this for a calculated column, but you could trivially rewrite it as a UDF or query calculation. Note that this logic rounds down fractional seconds; 00:00.00 to 00:00.999 is considered zero seconds, and displayed as "00:00:00".
If you anticipate that periods may be more than a few days long, this code switches to D:HH:MM:SS format when needed:
ElapsedTime AS
CASE WHEN DATEDIFF(S, StartDate, EndDate) >= 359999
THEN
CAST(DATEDIFF(S, StartDate, EndDate) / 86400 AS VARCHAR(7)) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 86400 / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
ELSE
RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
END
The following query should give the exact stuff you are looking out for.
select datediff(second, '2010-01-22 15:29:55.090' , '2010-01-22 15:30:09.153')
Here is the link from MSDN for what all you can do with datediff function .
https://msdn.microsoft.com/en-us/library/ms189794.aspx
Internally in SQL Server dates are stored as 2 integers. The first integer is the number of days before or after the base date (1900/01/01). The second integer stores the number of clock ticks after midnight, each tick is 1/300 of a second.
More info here
Because of this, I often find the simplest way to compare dates is to simply substract them. This handles 90% of my use cases. E.g.,
select date1, date2, date2 - date1 as DifferenceInDays
from MyTable
...
When I need an answer in units other than days, I will use DateDiff.
SELECT DATEDIFF(yyyy, '2011/08/25', '2017/08/25') AS DateDiff
It's gives you difference between two dates in Year
Here (2017-2011)=6 as a result
Syntax:
DATEDIFF(interval, date1, date2)
Use This for DD:MM:SS:
SELECT CONVERT(VARCHAR(max), Datediff(dd, '2019-08-14 03:16:51.360',
'2019-08-15 05:45:37.610'))
+ ':'
+ CONVERT(CHAR(8), Dateadd(s, Datediff(s, '2019-08-14 03:16:51.360',
'2019-08-15 05:45:37.610'), '1900-1-1'), 8)
So this isn't my answer but I just found this while searching around online for a question like this as well. This guy set up a procedure to calculate hours, minutes and seconds. The link and the code:
--Creating Function
If OBJECT_ID('UFN_HourMinuteSecond') Is Not Null
Drop Function dbo.UFN_HourMinuteSecond
Go
Exec(
'Create Function dbo.UFN_HourMinuteSecond
(
#StartDateTime DateTime,
#EndDateTime DateTime
) Returns Varchar(10)
As
Begin
Declare #Seconds Int,
#Minute Int,
#Hour Int,
#Elapsed Varchar(10)
Select #Seconds = ABS(DateDiff(SECOND ,#StartDateTime,#EndDateTime))
If #Seconds >= 60
Begin
select #Minute = #Seconds/60
select #Seconds = #Seconds%60
If #Minute >= 60
begin
select #hour = #Minute/60
select #Minute = #Minute%60
end
Else
Goto Final
End
Final:
Select #Hour = Isnull(#Hour,0), #Minute = IsNull(#Minute,0), #Seconds = IsNull(#Seconds,0)
select #Elapsed = Cast(#Hour as Varchar) + '':'' + Cast(#Minute as Varchar) + '':'' + Cast(#Seconds as Varchar)
Return (#Elapsed)
End'
)
declare #dt1 datetime='2012/06/13 08:11:12', #dt2 datetime='2012/06/12 02:11:12'
select CAST((#dt2-#dt1) as time(0))
PRINT DATEDIFF(second,'2010-01-22 15:29:55.090','2010-01-22 15:30:09.153')
select
datediff(millisecond,'2010-01-22 15:29:55.090','2010-01-22 15:30:09.153') / 1000.0 as Secs
result:
Secs
14.063
Just thought I'd mention it.
Sol-1:
select
StartTime
, EndTime
, CONVERT(NVARCHAR,(EndTime-StartTime), 108) as TimeDiff
from
[YourTable]
Sol-2:
select
StartTime
, EndTime
, DATEDIFF(hh, StartTime, EndTime)
, DATEDIFF(mi, StartTime, EndTime) % 60
from
[YourTable]
Sol-3:
select
DATEPART(hour,[EndTime]-[StartTime])
, DATEPART(minute,[EndTime]-[StartTime])
from
[YourTable]
Datepart works the best
Please check below trick to find the date difference between two dates
DATEDIFF(DAY,ordr.DocDate,RDR1.U_ProgDate) datedifff
where you can change according your requirement as you want difference of days or month or year or time.
CREATE FUNCTION getDateDiffHours(#fdate AS datetime,#tdate as datetime)
RETURNS varchar (50)
AS
BEGIN
DECLARE #cnt int
DECLARE #cntDate datetime
DECLARE #dayDiff int
DECLARE #dayDiffWk int
DECLARE #hrsDiff decimal(18)
DECLARE #markerFDate datetime
DECLARE #markerTDate datetime
DECLARE #fTime int
DECLARE #tTime int
DECLARE #nfTime varchar(8)
DECLARE #ntTime varchar(8)
DECLARE #nfdate datetime
DECLARE #ntdate datetime
-------------------------------------
--DECLARE #fdate datetime
--DECLARE #tdate datetime
--SET #fdate = '2005-04-18 00:00:00.000'
--SET #tdate = '2005-08-26 15:06:07.030'
-------------------------------------
DECLARE #tempdate datetime
--setting weekends
SET #fdate = dbo.getVDate(#fdate)
SET #tdate = dbo.getVDate(#tdate)
--RETURN #fdate
SET #fTime = datepart(hh,#fdate)
SET #tTime = datepart(hh,#tdate)
--RETURN #fTime
if datediff(hour,#fdate, #tdate) <= 9
RETURN(convert(varchar(50),0) + ' Days ' + convert(varchar(50),datediff(hour,#fdate, #tdate))) + ' Hours'
else
--setting working hours
SET #nfTime = dbo.getV00(convert(varchar(2),datepart(hh,#fdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,#fdate))) + ':'+ dbo.getV00(convert(varchar(2),datepart(ss,#fdate)))
SET #ntTime = dbo.getV00(convert(varchar(2),datepart(hh,#tdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,#tdate))) + ':'+ dbo.getV00(convert(varchar(2),datepart(ss,#tdate)))
IF #fTime > 17
begin
set #nfTime = '17:00:00'
end
else
begin
IF #fTime < 8
set #nfTime = '08:00:00'
end
IF #tTime > 17
begin
set #ntTime = '17:00:00'
end
else
begin
IF #tTime < 8
set #ntTime = '08:00:00'
end
-- used for working out whole days
SET #nfdate = dateadd(day,1,#fdate)
SET #ntdate = #tdate
SET #nfdate = convert(varchar,datepart(yyyy,#nfdate)) + '-' + convert(varchar,datepart(mm,#nfdate)) + '-' + convert(varchar,datepart(dd,#nfdate))
SET #ntdate = convert(varchar,datepart(yyyy,#ntdate)) + '-' + convert(varchar,datepart(mm,#ntdate)) + '-' + convert(varchar,datepart(dd,#ntdate))
SET #cnt = 0
SET #dayDiff = 0
SET #cntDate = #nfdate
SET #dayDiffWk = convert(decimal(18,2),#ntdate-#nfdate)
--select #nfdate,#ntdate
WHILE #cnt < #dayDiffWk
BEGIN
IF (NOT DATENAME(dw, #cntDate) = 'Saturday') AND (NOT DATENAME(dw, #cntDate) = 'Sunday')
BEGIN
SET #dayDiff = #dayDiff + 1
END
SET #cntDate = dateadd(day,1,#cntDate)
SET #cnt = #cnt + 1
END
--SET #dayDiff = convert(decimal(18,2),#ntdate-#nfdate) --datediff(day,#nfdate,#ntdate)
--SELECT #dayDiff
set #fdate = convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) + ' ' + #nfTime
set #tdate = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate)) + ' ' + #ntTime
set #markerFDate = convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) + ' ' + '17:00:00'
set #markerTDate = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate)) + ' ' + '08:00:00'
--select #fdate,#tdate
--select #markerFDate,#markerTDate
set #hrsDiff = convert(decimal(18,2),datediff(hh,#fdate,#markerFDate))
--select #hrsDiff
set #hrsDiff = #hrsDiff + convert(int,datediff(hh,#markerTDate,#tdate))
--select #fdate,#tdate
IF convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate))
BEGIN
--SET #hrsDiff = #hrsDiff - 9
Set #hrsdiff = datediff(hour,#fdate,#tdate)
END
--select FLOOR((#hrsDiff / 9))
IF (#hrsDiff / 9) > 0
BEGIN
SET #dayDiff = #dayDiff + FLOOR(#hrsDiff / 9)
SET #hrsDiff = #hrsDiff - FLOOR(#hrsDiff / 9)*9
END
--select convert(varchar(50),#dayDiff) + ' Days ' + convert(varchar(50),#hrsDiff) + ' Hours'
RETURN(convert(varchar(50),#dayDiff) + ' Days ' + convert(varchar(50),#hrsDiff)) + ' Hours'
END
For Me This worked Perfectly
Convert(varchar(8),DATEADD(SECOND,DATEDIFF(SECOND,LogInTime,LogOutTime),0),114)
and the Output is
HH:MM:SS which is shown accurately in my case.
Please try
DECLARE #articleDT DATETIME;
DECLARE #nowDate DATETIME;
-- Time of the ARTICLE created
SET #articleDT = '2012-04-01 08:10:16';
-- Simulation of NOW datetime
-- (in real world you would probably use GETDATE())
SET #nowDate = '2012-04-10 11:35:36';
-- Created 9 days ago.
SELECT 'Created ' + CAST(DATEDIFF(day, #articleDT, #nowDate) AS NVARCHAR(50)) + ' days ago.';
-- Created 1 weeks, 2 days, 3 hours, 25 minutes and 20 seconds ago.
SELECT 'Created '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 / 24 / 7 AS NVARCHAR(50)) + ' weeks, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 / 24 % 7 AS NVARCHAR(50)) + ' days, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 % 24 AS NVARCHAR(50)) + ' hours, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 % 60 AS NVARCHAR(50)) + ' minutes and '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) % 60 AS NVARCHAR(50)) + ' seconds ago.';
For MS SQL, you can convert the datetime value to a double value.
The integer part contains the number of days since 1900-01-01, the fractional part contains the time in hours.
So you can calculate date difference as:
cast(date1-date2 as FLOAT)

Calculating timespan with t-sql

Given two date/times:
#start_date = '2009-04-15 10:24:00.000'
#end_date = '2009-04-16 19:43:01.000'
Is it possible to calculate the time elapsed between the two dates in the following format
1d 9h 19m
You can get the difference between the two dates to whatever resolution you want (in your example, minutes):
DATEDIFF(minute, #start_date, #end_date)
From there it's a simple matter of dividing minutes into hours and hours into days and modding the remainder.
I know this thread is older and the original participants are likely no longer watching, but I stumbled upon it, and had already written some code fairly recently to do something very close to what jdiaz is requesting. The result is rendered as a string in D:H:M:S format.
Step one would be to get the time span in seconds:
DECLARE #ElapsedS INT
SET #ElapsedS = DATEDIFF(second, #start_date, #end_date)
Now create the following scalar function:
CREATE FUNCTION [dbo].[udfTimeSpanFromSeconds]
(
#Seconds int
)
RETURNS varchar(15)
AS
BEGIN
DECLARE
--Variable to hold our result
#DHMS varchar(15)
--Integers for doing the math
, #Days int --Integer days
, #Hours int --Integer hours
, #Minutes int --Integer minutes
--Strings for providing the display
, #sDays varchar(5) --String days
, #sHours varchar(2) --String hours
, #sMinutes varchar(2) --String minutes
, #sSeconds varchar(2) --String seconds
--Get the values using modulos where appropriate
SET #Hours = #Seconds/3600
SET #Minutes = (#Seconds % 3600) /60
SET #Seconds = (#Seconds % 3600) % 60
--If we have 24 or more hours, split the #Hours value into days and hours
IF #Hours > 23
BEGIN
SET #Days = #Hours/24
SET #Hours = (#Hours % 24)
END
ELSE
BEGIN
SET #Days = 0
END
--Now render the whole thing as string values for display
SET #sDays = convert(varchar, #Days)
SET #sHours = RIGHT('0' + convert(varchar, #Hours), 2)
SET #sMinutes = RIGHT('0' + convert(varchar, #Minutes), 2)
SET #sSeconds = RIGHT('0' + convert(varchar, #Seconds), 2)
--Concatenate, concatenate, concatenate
SET #DHMS = #sDays + ':' + #sHours + ':' + #sMinutes + ':' + #sSeconds
RETURN #DHMS
END
Now feed your timespan into the newly created function:
SELECT TimeSpan = dbo.udfTimeSpanFromSeconds(#ElapsedS)
Should produce '1:09:19:01'
CONVERT(
varchar(8),
(
CAST(#end_date AS DATETIME)
-
CAST(#start_date AS DATETIME)
)
,108
)
This'll give it to you as HH:MM:SS
Cheers
DATEDIFF can return unintuitive values. For example, the two dates below differ by one second yet DATEDIFF with the parameters below and interpreted as others have interpreted it above returns 1 year:
SELECT DATEDIFF(year, '2005-12-31 23:59:59', '2006-01-01 00:00:00')
Look at the MSDN documentation for DATEDIFF to understand how it works.
datediff(datepart, date1, date2);
Rex's answer is more complete.
Here's how you format the datediff (50d 8h 35m) in a query:
Declare #Date1 as Datetime, #Date2 as Datetime
Set #Date1 = '2005-01-01 08:00:00'
Set #Date2 = '2005-02-20 16:35:30'
Select
CAST(DATEDIFF(Minute,#Date1, #Date2)/60/24 as Varchar(50)) ++ 'd ' ++
CAST((DATEDIFF(Minute,#Date1, #Date2)/60)-((DATEDIFF(Minute,#Date1, #Date2)/60/24)*24) as Varchar(50)) ++ 'h ' ++
CAST((DATEDIFF(Minute,#Date1, #Date2)) - (DATEDIFF(HOUR,#Date1, #Date2)*60) as Varchar(50)) ++ 'm' as FormattedDateDiff
DECLARE #FirstDate DATETIME, #SecondDate DATETIME, #result VARCHAR(MAX)
SELECT #FirstDate = '2017-03-01 09:54:00.637', #SecondDate = GETDATE()
DECLARE #Day INT,#Month INT,#Hour INT, #Minute INT,#TotalSeconds INT,#Year INT
SELECT #TotalSeconds = ABS(DATEDIFF(SECOND,#FirstDate,#SecondDate))
-- Standard values in seconds
DECLARE #YearSeconds INT, #MonthSeconds INT, #DaySeconds INT, #HourSeconds INT, #MinuteSeconds INT
SELECT #MinuteSeconds = 60
SELECT #HourSeconds = 60 * #MinuteSeconds
SELECT #DaySeconds = 24 * #HourSeconds
SELECT #MonthSeconds = 30 * #DaySeconds
SELECT #YearSeconds = 12 * #MonthSeconds
--SELECT #MinuteSeconds AS [Minutes], #HourSeconds AS [Hours], #DaySeconds AS [Day],#MonthSeconds AS [Month],#YearSeconds AS [Year]
IF #TotalSeconds < #MinuteSeconds
BEGIN
SELECT #result = CAST(#TotalSeconds AS NVARCHAR(20)) + ' seconds ago'
END
ELSE IF #TotalSeconds < #HourSeconds
BEGIN
SELECT #result = CAST(ABS(DATEDIFF(MINUTE,#FirstDate,#SecondDate)) AS NVARCHAR(20)) + ' minutes ago'
END
ELSE IF #TotalSeconds < #DaySeconds
BEGIN
SELECT #result = CAST(ABS(DATEDIFF(HOUR,#FirstDate,#SecondDate)) AS NVARCHAR(20)) + ' hours ago'
END
ELSE IF #TotalSeconds < #MonthSeconds
BEGIN
SELECT #result = CAST(ABS(DATEDIFF(DAY,#FirstDate,#SecondDate)) AS NVARCHAR(20)) + ' days ago'
END
ELSE IF #TotalSeconds < #YearSeconds
BEGIN
SELECT #result = CAST(ABS(DATEDIFF(MONTH,#FirstDate,#SecondDate)) AS NVARCHAR(20)) + ' months ago'
END
ELSE IF #TotalSeconds > #YearSeconds
BEGIN
SELECT #result = CAST(ABS(DATEDIFF(YEAR,#FirstDate,#SecondDate)) AS NVARCHAR(20)) + ' year ago'
END
SELECT #result