Solved

calculate working hours in sql

Posted on 2006-07-19
4
881 Views
Last Modified: 2011-09-20
Hi

I am trying to calculate working hours from a table using sql, I currently have a Startdate eg. "29/06/2006 08:29:12" and a EndDate eg. "17/07/2006 08:32:28".
The working hours are specified as 08:15 - 13:00 (Lunch) and 14:00-16:30, Monday to Friday.

Can anyone show me a way to calculate working hours using Sql or would it be best to write a program to calculate this?


Thanks
Rui

 
0
Comment
Question by:ruimc
  • 2
  • 2
4 Comments
 
LVL 25

Expert Comment

by:Lee Savidge
ID: 17136915
Hi,

I do have some SQL that calculates the working hours between 2 dates but it doesn't cater for the lunch break, however this shouldn't be hard to add in. The stored procedure also relies on a SQL function that finds out if each day is a working day. This function further relies on a table containing non-working days, like Good Friday etc. I can post it if you want. Let me know.

Regards,

Lee
0
 

Author Comment

by:ruimc
ID: 17136949
Hi

That sounds good...yeah please post it I'd like to check out.

Regards,
Rui
0
 
LVL 25

Accepted Solution

by:
Lee Savidge earned 500 total points
ID: 17137232
Hi,

Here is the stored procedure and the function is listed afterwards. Remember this doesn't take into account the lunch hour but realistically that can't be too hard to factor in. The table in the function "NonWorkingDays" contains a list of dates that are non working days based on the the UK government DTI web page here http://www.dti.gov.uk/employment/bank-public-holidays/index.html.

This should get you started. Hope it helps.

Lee


if exists (select * from sysobjects where name = N'CalcWorkingHours' and type = N'FN')
    drop function CalcWorkingHours
go

CREATE FUNCTION CalcWorkingHours (@dtStartDateTime AS DATETIME,
                                  @dtEndDateTime AS DATETIME,
                                  @dtWorkFrom AS DATETIME,
                                  @dtWorkTo AS DATETIME)
RETURNS VARCHAR(10)
AS
BEGIN

    DECLARE @intWorkingMinutes        INT,
            @intFullWorkDayMinutes    INT,
            @intHours                 INT,
            @intMinutes               INT,
            @dtFirstDayEnd            DATETIME,
            @dtLastDayStart           DATETIME,
            @chrWorkingHours          VARCHAR(10),
            @chrHours                 VARCHAR(7),
            @chrMinutes               VARCHAR(2)

    SELECT  @intWorkingMinutes = 0
    SELECT  @intFullWorkDayMinutes = DATEDIFF(mi, @dtWorkFrom, @dtWorkTo)

    -- Is the start date & time < end date & time
    IF DATEDIFF(dd, @dtStartDateTime, @dtEndDateTime) >= 0
    BEGIN

        -- If start and end time are the same assume 24 hour workig day
        IF @intFullWorkDayMinutes = 0
        BEGIN
            SELECT @intWorkingMinutes = DATEDIFF(mi, @dtStartDateTime, @dtEndDateTime)
        END
        ELSE
        BEGIN

            -- Is the start time < working hours start
            IF DATEPART(hh, @dtStartDateTime) < DATEPART(hh, @dtWorkFrom)
            BEGIN
                SELECT @dtStartDateTime = LEFT(@dtStartDateTime, 12) + RIGHT(@dtWorkFrom, 6)
            END
            ELSE
            BEGIN

                -- Is the start time > working hours end
                IF DATEPART(hh, @dtStartDateTime) >= DATEPART(hh, @dtWorkTo)
                BEGIN
                    SELECT @dtStartDateTime = LEFT(@dtStartDateTime, 12) + RIGHT(@dtWorkTo, 6)
                END
            END

            -- Is the end time < working hours start
            IF DATEPART(hh, @dtEndDateTime) < DATEPART(hh, @dtWorkFrom)
            BEGIN
                SELECT @dtEndDateTime = LEFT(@dtEndDateTime, 12) + RIGHT(@dtWorkFrom, 6)
            END
            ELSE
            BEGIN

                -- Is the end time > working hours end
                IF DATEPART(hh, @dtEndDateTime) >= DATEPART(hh, @dtWorkTo)
                BEGIN
                    SELECT @dtEndDateTime = LEFT(@dtEndDateTime, 12) + RIGHT(@dtWorkTo, 6)
                END
            END

            -- Are start date and end date the same
            IF DATEDIFF(dd, @dtStartDateTime, @dtEndDateTime) = 0
            BEGIN

                -- Is this a working day?
                IF dbo.WorkingDay(@dtStartDateTime) = 1
                BEGIN
                    SELECT @intWorkingMinutes = DATEDIFF(mi, @dtStartDateTime, @dtEndDateTime)
                END
                ELSE
                BEGIN
                    SELECT @intWorkingMinutes = 0
                END
            END
            ELSE
            BEGIN

                -- Calculate the number of minutes on the first day
                SELECT @dtFirstDayEnd = LEFT(@dtStartDateTime, 12) + RIGHT(@dtWorkTo, 6)
                -- Is this a working day?
                IF dbo.WorkingDay(@dtStartDateTime) = 1
                BEGIN
                    SELECT @intWorkingMinutes = DATEDIFF(mi, @dtStartDateTime, @dtFirstDayEnd)
                END
                SELECT @dtStartDateTime = DATEADD(dd, 1, @dtStartDateTime)

                -- Calculate the number of minutes on the last day
                SELECT @dtLastDayStart = LEFT(@dtEndDateTime, 12) + RIGHT(@dtWorkFrom, 6)
                -- Is this a working day?
                IF dbo.WorkingDay(@dtLastDayStart) = 1
                BEGIN
                    SELECT @intWorkingMinutes = @intWorkingMinutes + DATEDIFF(mi, @dtLastDayStart, @dtEndDateTime)
                END

                -- Calculate the number of working days between the two dates
                WHILE CONVERT(DATETIME, LEFT(@dtStartDateTime, 12)) < CONVERT(DATETIME, LEFT(@dtEndDateTime, 12))
                BEGIN

                    -- Is this a working day?
                    IF dbo.WorkingDay(@dtStartDateTime) = 1
                    BEGIN
                        SELECT @intWorkingMinutes = @intWorkingMinutes + @intFullWorkDayMinutes
                    END
                    SELECT @dtStartDateTime = DATEADD(dd, 1, @dtStartDateTime)
                END
            END
        END
    END
    ELSE
    BEGIN
        SELECT @intWorkingMinutes = 0
    END

    -- Calculate hours and minutes
    SELECT @intHours = @intWorkingMinutes / 60
    SELECT @chrHours = CAST(@intHours AS VARCHAR(7))
    IF LEN(@chrHours) < 2
    BEGIN
        SELECT @chrHours = REPLICATE('0', 2 - LEN(@chrHours)) + @chrHours
    END
    SELECT @intMinutes = @intWorkingMinutes - (@intHours * 60)
    SELECT @chrMinutes = CAST(@intMinutes AS VARCHAR(2))
    SELECT @chrMinutes = REPLICATE('0', 2 - LEN(@chrMinutes)) + @chrMinutes
    SELECT @chrWorkingHours = @chrHours + ':' + @chrMinutes

    return @chrWorkingHours
END
GO

GRANT EXECUTE on CalcWorkingHours TO PUBLIC
GO

--------------------- End of stored procedure --------------------

--------------------- Function start -------------------

if exists (select * from sysobjects where name = N'WorkingDay' and type = N'FN')
    drop function WorkingDay
go

CREATE FUNCTION WorkingDay (@dtDate AS DATETIME)
RETURNS BIT
AS
BEGIN

    DECLARE @bWorkingDay BIT
    SELECT  @bWorkingDay = 1

    -- Check for a weekend
    IF DATEPART(dw, @dtDate) IN (1, 7)
    BEGIN
        SELECT @bWorkingDay = 0
    END
    ELSE
    BEGIN

        -- Check for a public holiday
        IF EXISTS (SELECT    *
                    FROM      NonWorkingDays
                    WHERE     dtNonWorkingDay = LEFT(@dtDate, 11)    AND
                              chCountryCode = 'GB'                   AND
                              tiRecordStatus = 1)
        BEGIN
            SELECT @bWorkingDay = 0
        END
    END

    RETURN @bWorkingDay
END
GO

GRANT EXECUTE on WorkingDay TO PUBLIC
GO


----------------- End of function -------------------

0
 

Author Comment

by:ruimc
ID: 17146547
Excellent...Thanks. I have a public holiday table already setup for the sms program so it's all good.
It did indeed help and saved me plenty time. Thanks. The points are yours.

 
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction SQL Server Integration Services can read XML files, that’s known by every BI developer.  (If you didn’t, don’t worry, I’m aiming this article at newcomers as well.) But how far can you go?  When does the XML Source component become …
I have a large data set and a SSIS package. How can I load this file in multi threading?
Via a live example, show how to extract information from SQL Server on Database, Connection and Server properties
Using examples as well as descriptions, and references to Books Online, show the different Recovery Models available in SQL Server and explain, as well as show how full, differential and transaction log backups are performed

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question