Calculate Time Difference in hh:mm - sql-server

I have this query but I'm not sure what function to use so I can get time difference in this "hh:mm" format. Can anybody help ?
SELECT
EI.[FirstName]+' '+EI.[LastName] [EmployeeName], [Dpt].[FullName] [Department], [Desig].[FullName] [Designation],
FirstIN = CAST(MIN([AttendanceTimeIn]) AS TIME),
LastOUT = CAST(MAX([AttendanceTimeOut]) AS TIME),
HoursSpent = DATEDIFF(HOUR, CAST(MIN(AttendanceTimeIn) AS TIME), CAST(MAX(AttendanceTimeOut) AS TIME)),
CAST(COALESCE(AttendanceTimeIn, AttendanceTimeOut) AS DATE) [Date]
FROM [HRM].[tbl_Designation] [Desig], [HRM].[tbl_Department] [Dpt], [HRM].[tbl_EmployeeInfo] [EI]
FULL OUTER JOIN [HRM].[tbl_EmployeeAttendance] [Attendance] ON [Attendance].[EmpCode] = [EI].[ID]
WHERE
[Dpt].[ID] = [EI].[DeptCode] AND [Desig].[ID] = [EI].[DesignationCode]
AND
[EI].[RecordStatusCode] != '13'
AND
CAST((GETDATE()-1) AS DATE) = CAST(ISNULL([AttendanceTimeIn], [AttendanceTimeOut]) AS Date)
GROUP BY
EI.[FirstName]+' '+EI.[LastName], [Dpt].[FullName], [Desig].[FullName], CAST(COALESCE(AttendanceTimeIn, AttendanceTimeOut) AS DATE)

Maybe you can use something like this:
declare #d1 datetime = '2018-01-11 23:40:18.010'
declare #d2 datetime = '2018-01-12 11:59:18.010'
SELECT CONVERT(VARCHAR(2),DATEPART(HOUR,#d2 - #d1)) + ':' + CONVERT(VARCHAR(2),DATEPART(MINUTE,#d2 - #d1));

If to leave out your concept of using the time for the duration, you can use a query like below:
DECLARE #d1 DATETIME
DECLARE #d2 DATETIME
SELECT #d1 = GETDATE() - 1.465, #d2 = GETDATE()
SELECT
FirstIN = #d1,
LastOUT = #d2,
HoursSpent = CAST(DATEDIFF(HOUR, #d1, #d2) AS VARCHAR) + ':' + RIGHT('0' + CAST(DATEDIFF(MINUTE, #d1, #d2) % 60 AS VARCHAR), 2)

Let's expand step by step:
declare
#start datetime = getdate(),
#end datetime = dateadd(second, getdate(), 5000)
-- datediff(hour, #start, #end) -> hour difference
-- dateadd(hour, #start, datediff(hour, #start, #end)) -> start + integer hour difference to get less-than-an-hour diff
-- datediff(minute, dateadd(hour, #start, datediff(hour, #start, #end)), #end) -> minute difference from there
select
cast(datediff(hour, #start, #end) as varchar(2))
+ ':'
+ cast(datediff(minute, dateadd(hour, #start, datediff(hour, #start, #end)), #end) as varchar(2)) as [hh:mm]

Related

Convert nvarchar to datetime sql server

I try to convert 2016/07/15 (nvarchar format) to this datetime format 2016-07-15 00:00:00 in sql server. But i need the time part to be the current time. can any one help ?
This is my sp:
declare #DateTime varchar(50)
set #DateTime = '2016/07/15'
select convert(varchar, cast(#DateTime as datetime), 120)
You can use this:
declare #DateTime varchar(50)
set #DateTime = CONCAT('2016/07/15' , ' ', CONVERT(TIME, GETDATE()))
select #DateTime
select convert(varchar, cast(#DateTime as datetime2(7)), 120)
Or replace the CONCAT with:
set #DateTime = '2016/07/15' + ' ' + CONVERT(NVARCHAR(50), CONVERT(TIME, GETDATE()))
Try this...
Just concat time with your output
declare #DateTime varchar(50)
set #DateTime = '2016/07/15'
select convert(varchar, cast(#DateTime as datetime), 101) + ' ' + CONVERT(varchar, getdate(),108)
Try like this,
DECLARE #DateTime VARCHAR(50)
SET #DateTime = '2016/07/15'
SELECT DATEADD(day, 0, DATEDIFF(day, 0, #DateTime)) + DATEADD(day, 0 - DATEDIFF(day, 0, getdate()), getdate())

SQL server date time

I am trying to get object which its start date + start time have passed or equal to current datetime and its end date + end time hasn't pass the current datetime. I tried convert current datetime to nvarchar as all my columns are nvarchar. I also tried converting my columns to datetime type but it doesn't work too. Please help
Column:
startDate - nvarchar (dd/mm/yyyy)
startTime - nvarchar (hh:mm) 24 hr
endDate - nvarchar(dd/mm/yyyy)
endTime - nvarchar(hh:mm) 24hr
i did try to but datetime betwween startDate + startTime AND endDate +startTime,
but it doesn't seems to work :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2) BETWEEN
startDate + ' ' + startTime
AND endDate + ' ' + endTime
i did try other method too :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND startDate + ' ' + startTime <= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
AND endDate + ' ' + endTime >= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
You could do it like this:
SELECT *
FROM Promo
WHERE
membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME) BETWEEN
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
AND CONVERT(DATETIME, #endDate, 103) + CONVERT(DATETIME, #endTime)
This line:
CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME)
gets the current date time up to its minutes, meaning this will strip off the seconds and milliseconds part of the GETDATE().
And this line:
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
will combine your date and time variables to form a new DATETIME value.
Note that you could have done away with with this if you design the tables using the proper data types.
Try this
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GetDate(), 120) AS DATETIME)
BETWEEN CONVERT(DATETIME, startDate + ' ' + startTime, 120)
AND CONVERT(DATETIME, endDate + ' ' + endTime, 120)

How to get Hour and minutes in decimal format from two dates

Here is my query
select DATEDIFF(minute, '2015-06-10 14:00:00.000', '2015-06-10 16:50:00.000') / 60.0
I get 2.833333 but i want 2.50
This gives you what you asked for, but please keep in mind that usually 2.50 is equal to 2.5 and means 5/2; you are using a notation that it is quite uncommon
DECLARE #f float
DECLARE #t nvarchar(15)
SELECT #f = DATEDIFF(hour, '2015-06-10 14:00:00.000', '2015-06-10 16:50:00.000')
SELECT #t = CONVERT(nvarchar(10), #f) + N'.' + CONVERT(nvarchar(10), (DATEDIFF(minute, '2015-06-10 14:00:00.000', '2015-06-10 16:50:00.000') - #f*60))
SELECT #t
So you want to show the hours and minutes? You could use this:
DECLARE #t1 datetime
SET #t1 = '2015-06-10 14:00:00.000'
DECLARE #t2 datetime
SET #t2 = '2015-06-10 16:50:00.000'
SELECT HHmm = CONVERT(varchar(3), DATEDIFF(minute, #t1, #t2) / 60)
+ '.'
+ RIGHT('0' + CONVERT(varchar(2), DATEDIFF(minute, #t1, #t2) % 60), 2)
Demo
The DateDiff function returns an integer. to display it as time you need to use some math and casting:
DECLARE #FromDate datetime = '2015-06-10 14:00:00.000',
#ToDate datetime = '2015-06-10 16:50:00.000'
select CAST(DATEDIFF(minute, #FromDate, #ToDate) / 60 as varchar) + ':' +
CAST(DATEDIFF(minute, #FromDate, #ToDate) % 60 as varchar)

PL/SQL to TSQL conversion

I have used a tool to convert PL/SQL to TSQL but I am getting weird errors for some cases.
CREATE PROC Dates
(
#PeriodType varchar(15),
#ReportStart varchar(15),
#ReportEnd varchar(15)
)
AS
BEGIN
SELECT CASE
WHEN #PeriodType = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 1, 112))
WHEN #PeriodType = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 6 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 13, 112))
WHEN #PeriodType = 'CUR_MONTH' THEN CONVERT(DATETIME, CAST(CONVERT(VARCHAR(23), GETDATE()) AS VARCHAR) + '01', 112)
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportStart)
END AS "StartDate",
CASE
WHEN #PeriodType = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 15 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) + 1 - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1, 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(M, 1, CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (CONVERT(NUMERIC(8, 2), DATEPART(DD, GETDATE())) - 1)) - 1
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportEnd) + 1
END AS "EndDate"
END
My stored proc is executing for PREV_DAY and PREV_2WEEK for the remaining period type I am getting conversions errors.
exec proc Dates 'PREV_DAY','',''
exec proc Dates 'PREV_2WEEK','',''
My PL\SQL code is
SELECT CASE
WHEN :PeriodType = 'CUR_WEEK'
THEN TRUNC(SYSDATE + 1 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'NEXT_WEEK'
THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'PREV_DAY'
THEN TRUNC(SYSDATE - 1)
WHEN :PeriodType = 'PREV_WEEK'
THEN TRUNC(SYSDATE - 6 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'PREV_2WEEK'
THEN TRUNC(SYSDATE - 13)
WHEN :PeriodType = 'CUR_MONTH'
THEN to_date(to_char(sysdate,'YYYYMM') || '01','YYYYMMDD')
WHEN :PeriodType = 'DATE_RANGE'
THEN TO_DATE(:ReportStart)
END AS "StartDate",
CASE
WHEN :PeriodType = 'CUR_WEEK'
THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
WHEN :PeriodType = 'NEXT_WEEK'
THEN TRUNC(SYSDATE + 15 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
WHEN :PeriodType = 'PREV_DAY'
THEN TRUNC(SYSDATE)-(1/86400)
WHEN :PeriodType = 'PREV_WEEK'
THEN TRUNC(SYSDATE - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) + 1 - (1/86400)
WHEN :PeriodType = 'PREV_2WEEK'
THEN TRUNC ( SYSDATE+1) - (1/86400)
WHEN :PeriodType = 'CUR_MONTH'
THEN ADD_MONTHS(TRUNC(SYSDATE) - (TO_NUMBER(TO_CHAR(SYSDATE,'DD')) - 1), 1) -1
WHEN :PeriodType = 'DATE_RANGE'
THEN TO_DATE(:ReportEnd)+1
END AS "EndDate"
FROM DUAL
At least one problem is this expression in the first then clause:
CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE()))
This expression:
select CONVERT(VARCHAR(23), GETDATE())
just returned:
May 23 2014 3:01AM
And that just won't convert to numeric.
I think you need to go through the code line by line to figure out the best way to do things. Also, whenever you use varchar or char, you should have a length associated with them. The default is sometimes (but not always) 1, and that can cause problems.
Oracle and SQLServer work with datetime in different manner.
The tool converted the script as well as a string parser can, like someone translating a quote word by word between two languages.
In SQLServer to work with that data type you have to use the functions DATEADD, DATEDIFF and other ones that can be found on the help page from MS.
Using the date function of SQLServer the original function translate to
CREATE PROC Dates(
#PeriodType varchar(15),
#ReportStart varchar(15),
#ReportEnd varchar(15)
)
AS
BEGIN
SELECT CASE WHEN #PeriodType = 'CUR_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'NEXT_WEEK' THEN DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_DAY' THEN DATEADD(DAY, -1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) - 6, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_2WEEK' THEN DATEADD(DAY, - 13, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, - DATEPART(DAY, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportStart)
END AS StartDate,
, CASE WHEN #PeriodType = 'CUR_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'NEXT_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 15 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_DAY' THEN DATEADD(mi, -1, DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_2WEEK' THEN DATEADD(mi, -1, cast(cast(dateadd(DAY, 1, GETDATE()) AS date) AS datetime))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, -1, DATEADD(mm, DATEDIFF(mm, 0, cast(cast(GETDATE() AS date) AS datetime))+1,0))
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportEnd) + 1
END AS EndDate
END
The double CAST in CAST(CAST(GETDATE() AS DATE) AS DATETIME) is a little hack to get midnight of today, as GETDATE() is of datetime type and returns the current date and time.

T-SQL Date Difference for WeekDays only

I am trying to get the date difference in a given date excluding the week days.
Here is what I have:
SELECT DATEADD (w, -4, GETDATE())
This returns 2013-05-04 19:01:53.170, which means that it also counts weekends.
Same for
SELECT DATEADD (dw, -4, GETDATE())
Any help will be appreciated.
Thanks in advance.
I'm using these functions that return the non-weekend seconds between two dates:
CREATE FUNCTION [dbo].[DateDiff_NoWeekends](
#date1 DATETIME,
#date2 DATETIME
)
RETURNS INT AS BEGIN
DECLARE #retValue INT
SET #date1 = dbo.__CorrectDate(#date1, 1)
SET #date2 = dbo.__CorrectDate(#date2, 0)
IF (#date1 >= #date2)
SET #retValue = 0
ELSE BEGIN
DECLARE #days INT, #weekday INT
SET #days = DATEDIFF(d, #date1, #date2)
SET #weekday = DATEPART(dw, #date1) - 1
SET #retValue = DATEDIFF(s, #date1, #date2) - 2 * 24 * 3600 * ((#days + #weekday) / 7)
END
RETURN #retValue
END
GO
CREATE FUNCTION [dbo].[__CorrectDate](
#date DATETIME,
#forward INT
)
RETURNS DATETIME AS BEGIN
IF (DATEPART(dw, #date) > 5) BEGIN
IF (#forward = 1) BEGIN
SET #date = #date + (8 - DATEPART(dw, #date))
SET #date = DateAdd(Hour, (8 - DatePart(Hour, #date)), #date)
END ELSE BEGIN
SET #date = #date - (DATEPART(dw, #date)- 5)
SET #date = DateAdd(Hour, (18 - DatePart(Hour, #date)), #date)
END
SET #date = DateAdd(Minute, -DatePart(Minute, #date), #date)
SET #date = DateAdd(Second, -DatePart(Second, #date), #date)
END
RETURN #date
END
Here's a sql-fiddle demo for all non-weekend days in april (22).
SELECT [no weekend days in april] =
(dbo.DateDiff_NoWeekends('2013-04-01','2013-05-01')
/ 3600 / 24)
The query below gives the difference for week days alone , Ie counts the no od days between two days and subtracts the no of weekend days ,
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SELECT #StartDate = '01-July-2008',
#EndDate = '30-July-2008'
;WITH DATE (Date1)
AS (
SELECT DATEADD(DAY, DATEDIFF(DAY, '19000101', #StartDate), '19000101')
UNION ALL
SELECT DATEADD(DAY, 1, Date1)
FROM DATE
WHERE Date1 < #EndDate
)
SELECT count(*) -
(
SELECT count(*)
--CONVERT(VARCHAR(15),d1.DATE1 ,110) as [Working Date],
--DATENAME(weekday, d1.Date1) [Working Day]
from DATE d1 where (DATENAME(weekday, d1.Date1)) in ('Saturday','Sunday')
)
--CONVERT(VARCHAR(15),d1.DATE1 ,110) as [Working Date],
--DATENAME(weekday, d1.Date1) [Working Day]
from DATE d1 where (DATENAME(weekday, d1.Date1)) not in ('Saturday','Sunday')
please let me know for any clarifications
Maybe I am still missing some full testing, but this works for me too: take the difference in days and then subtract 2 days for each weekend
DateDiff(d, d1, d2) - 2*DateDiff(wk, d1, d2)
Could be put in a function as well

Resources