Home > Software engineering >  How to calculate time difference between 2 different DATETIME columns in order to display the output
How to calculate time difference between 2 different DATETIME columns in order to display the output

Time:03-26

Below is the table I have created and inserted values in it:

CREATE TABLE Attendance
(
  ClockedIn  DATETIME, 
  ClockedOut DATETIME
)

INSERT INTO Attendance(ClockedIn, ClockedOut) 
VALUES ('20160101 09:30:00','20160101 18:30:00'),
('20160201 08:10:00','20160201 18:20:00')

Now I am trying to solve a query which will display a person who has attended or worked for how many hours on that particular date. The query result that I want to should display something like which is shown below:

Clocked In                    Clocked Out                  Hours
2016-01-01 09:30:00.000       2016-01-01 18:30:00.000      9.00
2016-02-01 08:10:00.000       2016-02-01 18:20:00.000      10.10

This is what I have tried:

SELECT ClockedIn, ClockedOut,
CONVERT(VARCHAR,DATEPART(HOUR,ClockedOut - ClockedIn))   ':'   CONVERT(VARCHAR,DATEPART(MINUTE,ClockedOut - ClockedIn)) AS 'Hours'
FROM Attendance

And I got the following output:

enter image description here

I almost got the result that I wanted but the only issue is I am getting 9:0 instead of 9:00.

I even tried replacing MINUTE with MM inside the DATEPART and I got the following result:

enter image description here

As you can see from screenshot above, I got a wrong result.

What changes do I need to make in my existing query in order to display 9:00 instead of 9:0 ?

CodePudding user response:

I'm assuming that your times are in whole minutes. Here's are some ways that avoid invoking format():

concat(
    datediff(second, ClockedIn, ClockedOut) / 3600, ':',
    right('0'   cast(datediff(second, ClockedIn, ClockedOut) % 3600 / 60 as varchar(2)), 2)
)

concat(
    datediff(second, ClockedIn, ClockedOut) / 3600,
    left(concat(':', datediff(second, ClockedIn, ClockedOut) % 3600 / 60, '0'), 3))

The trick for zero-padding it to add in the extra 0 but then trim it down to the number you really want.

CodePudding user response:

As an alternative, which is longer, but maybe clearer to see what is going on, you can split out the calculations using CROSS APPLY to avoid repeating them. And you can if you wish convert to a datatime in order to make use of FORMAT which allows full control over formatting.

SELECT ClockedIn, ClockedOut
   -- Pad out missing zeros and display.
   , RIGHT('0'   CONVERT(varchar(2),C2.Hh),2)   ':'   RIGHT('0'   CONVERT(varchar(2),C2.Mm),2) [Hours 1]
   -- Optional, convert to a datetime datatype and then use FORMAT for full control over formatting
   , FORMAT(CONVERT(datetime2(0), RIGHT('0'   CONVERT(varchar(2),C2.Hh),2)   ':'   RIGHT('0'   CONVERT(varchar(2),C2.Mm),2)   ':00'), 'HH:mm') [Hours 2]
FROM Attendance A
CROSS APPLY (
    -- Calculate seconds, because its a lower unit then the lowest required
    VALUES (CONVERT(int, DATEDIFF(second, A.ClockedIn, A.ClockedOut) * 1.0 / 60))
) C1 (DiffInMinutes)
CROSS APPLY (
    -- Calculates hours and minutes
    VALUES (C1.DiffInMinutes / 60, C1.DiffInMinutes % 60)
) C2 (Hh, Mm);

Returns:

ClockedIn ClockedOut Hours 1 Hours 2
2016-01-01 09:30:00.000 2016-01-01 18:30:00.000 09:00 09:00
2016-02-01 08:10:00.000 2016-02-01 18:20:00.000 10:10 10:10

CodePudding user response:

I have finally solved it

This is what I have done:

SELECT ClockedIn, ClockedOut,
    FORMAT((CONVERT(DATETIME,ClockedOut) - CONVERT(DATETIME,ClockedIn)),'h:mm') AS 'Hours'
FROM Attendance

And I got my desired output:

enter image description here

  • Related