Solved

calculate working hours in sql

Posted on 2006-07-19
4
889 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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

Enterprise Mobility and BYOD For Dummies

Like “For Dummies” books, you can read this in whatever order you choose and learn about mobility and BYOD; and how to put a competitive mobile infrastructure in place. Developed for SMBs and large enterprises alike, you will find helpful use cases, planning, and implementation.

Question has a verified solution.

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

This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
Slowly Changing Dimension Transformation component in data task flow is very useful for us to manage and control how data changes in SSIS.
Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
Via a live example, show how to extract information from SQL Server on Database, Connection and Server properties

615 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