Calculate business hours between two dates

前端 未结 14 1347
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 05:06

How can I calculate business hours between two dates? For example we have two dates; 01/01/2010 15:00 and 04/01/2010 12:00 And we have working hours 09:00 to 17:00 in weekda

14条回答
  •  时光说笑
    2020-11-27 05:51

    A version I wrote today taking into account bank holidays. Note: This is not thoroughly tested and could no doubt be improved.

    CREATE FUNCTION [dbo].[WorkingHoursBetween2Dates]
    (
        @dtFrom datetime,
        @dtTo datetime
    )
    RETURNS INT
    BEGIN
        DECLARE @tblDates AS TABLE (DateValue DATE)
        DECLARE @dFrom date = @dtFrom
        DECLARE @dTo date = @dtTo
        DECLARE @intDays int
        DECLARE @intHours int = 0
        DECLARE @dFromWorkday bit = CASE WHEN (DATENAME(WEEKDAY, @dFrom) IN ('Saturday','Sunday')) OR EXISTS (SELECT * FROM dbo.BankHolidays WHERE BankHolidayDate = @dFrom) THEN 0 ELSE 1 END
        DECLARE @dToWorkday bit = CASE WHEN (DATENAME(WEEKDAY, @dTo) IN ('Saturday','Sunday')) OR EXISTS (SELECT * FROM dbo.BankHolidays WHERE BankHolidayDate = @dTo) THEN 0 ELSE 1 END
    
    
    
        IF DATEPART(HOUR,@dtFrom) < 9
            SET @dtFrom = DATEADD(HOUR,9,CAST(CAST(@dtFrom AS DATE) AS DATETIME))
        ELSE
            IF DATEPART(HOUR,@dtFrom) > 17
                SET @dtFrom = DATEADD(HOUR,17,CAST(CAST(@dtFrom AS DATE) AS DATETIME))
    
        IF DATEPART(HOUR,@dtTo) < 9
            SET @dtTo = DATEADD(HOUR,9,CAST(CAST(@dtTo AS DATE) AS DATETIME))
        ELSE
            IF DATEPART(HOUR,@dtTo) > 17
                SET @dtTo = DATEADD(HOUR,17,CAST(CAST(@dtTo AS DATE) AS DATETIME))
    
    
    
        WHILE @dFrom <= @dTo
        BEGIN
            INSERT INTO @tblDates
            (
                DateValue
            )
                SELECT @dFrom
                WHERE NOT ((DATENAME(WEEKDAY, @dFrom) IN ('Saturday','Sunday')) OR EXISTS (SELECT * FROM dbo.BankHolidays WHERE BankHolidayDate = @dFrom))
            
            SET @dFrom = DATEADD(DAY,1,@dFrom)
        END
        
        SET @intDays = CASE WHEN EXISTS(SELECT * FROM @tblDates) THEN (SELECT COUNT(*) FROM @tblDates) - 1 ELSE 0 END
    
        IF @intDays = 0
            BEGIN
                IF @dFromWorkday = 1
                    IF DATEPART(HOUR,@dtFrom) < 17
                        BEGIN
                            IF DATEDIFF(DAY,@dtFrom,@dtTo)=0
                                SET @intHours = DATEDIFF(HOUR,@dtFrom,@dtTo)
                            ELSE
                                SET @intHours = DATEDIFF(HOUR,@dtFrom,DATEADD(HOUR,17,CAST(CAST(@dtFrom AS DATE) AS DATETIME)))
                        END
    
                IF @dToWorkday = 1 AND DATEDIFF(DAY,@dtFrom,@dtTo)<>0
                    IF DATEPART(HOUR,@dtTo) >= 17
                        SET @intHours = @intHours + 8
                    ELSE
                        IF DATEPART(HOUR,@dtTo) > 9
                            SET @intHours = @intHours + DATEPART(HOUR,@dtTo) - 9
            END
        ELSE
            BEGIN
                IF @dFromWorkday = 1
                    IF DATEPART(HOUR,@dtFrom) < 17
                        BEGIN
                            SET @intHours = DATEDIFF(HOUR,@dtFrom,DATEADD(HOUR,17,CAST(CAST(@dtFrom AS DATE) AS DATETIME)))
                            SET @intDays = @intDays - 1
                        END
    
                IF DATEPART(HOUR,@dtTo) < 17
                    SET @intHours = @intHours + (@intDays * 8) + CASE WHEN @dToWorkday = 1 THEN DATEDIFF(HOUR,DATEADD(HOUR,9,CAST(CAST(@dtTo AS DATE) AS DATETIME)), @dtTo) ELSE 0 END
                ELSE
                    SET @intHours = @intHours + ((@intDays + 1) * 8)
            END
    
        RETURN (@intHours)
    END
    

提交回复
热议问题