Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

calculate working hours in sql

Posted on 2006-07-19
4
Medium Priority
?
894 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 2000 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

Survive A High-Traffic Event with Percona

Your application or website rely on your database to deliver information about products and services to your customers. You can’t afford to have your database lose performance, lose availability or become unresponsive – even for just a few minutes.

Question has a verified solution.

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

For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
An alternative to the "For XML" way of pivoting and concatenating result sets into strings, and an easy introduction to "common table expressions" (CTEs). Being someone who is always looking for alternatives to "work your data", I came across this …
Using examples as well as descriptions, and references to Books Online, show the documentation available for datatypes, explain the available data types and show how data can be passed into and out of variables.
Viewers will learn how the fundamental information of how to create a table.

715 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