计算两个日期之间的秒数,包括营业时间(节假日除外),开始时间08:30

时间:2018-12-10 10:19:07

标签: sql sql-server-2008 datetime

在寻找问题的解决方案时,我发现了以下sql(Calculate business hours between two dates)。

但是,我希望起点是8:30而不是9,终点是17:30而不是17。目前,我正在使用整数。谁能帮我这个?预先感谢!

    Create Function GetWorkingMin(@StartDate DateTime, @EndDate DateTime, @Country Varchar(2)) Returns Int 
AS
Begin
Declare @WorkMin int = 0   -- Initialize counter
Declare @Reverse bit       -- Flag to hold if direction is reverse
Declare @StartHour int = 9   -- Start of business hours (can be supplied as an argument if needed)
Declare @EndHour int = 17    -- End of business hours (can be supplied as an argument if needed)
Declare @Holidays Table (HDate DateTime)   --  Table variable to hold holidayes

-- If dates are in reverse order, switch them and set flag
If @StartDate>@EndDate 
Begin
    Declare @TempDate DateTime=@StartDate
    Set @StartDate=@EndDate
    Set @EndDate=@TempDate
    Set @Reverse=1
End
Else Set @Reverse = 0

-- Get country holidays from table based on the country code (Feel free to remove this or modify as per your DB schema)
Insert Into @Holidays (HDate) Select HDate from HOLIDAY Where COUNTRYCODE=@Country and HDATE>=DateAdd(dd, DateDiff(dd,0,@StartDate), 0)

If DatePart(HH, @StartDate)<@StartHour Set @StartDate = DateAdd(hour, @StartHour, DateDiff(DAY, 0, @StartDate))  -- If Start time is less than start hour, set it to start hour
If DatePart(HH, @StartDate)>=@EndHour+1 Set @StartDate = DateAdd(hour, @StartHour+24, DateDiff(DAY, 0, @StartDate)) -- If Start time is after end hour, set it to start hour of next day
If DatePart(HH, @EndDate)>=@EndHour+1 Set @EndDate = DateAdd(hour, @EndHour, DateDiff(DAY, 0, @EndDate)) -- If End time is after end hour, set it to end hour
If DatePart(HH, @EndDate)<@StartHour Set @EndDate = DateAdd(hour, @EndHour-24, DateDiff(DAY, 0, @EndDate)) -- If End time is before start hour, set it to end hour of previous day

If @StartDate>@EndDate Return 0

-- If Start and End is on same day
If DateDiff(Day,@StartDate,@EndDate) <= 0
Begin
    If Datepart(dw,@StartDate)>1 And DATEPART(dw,@StartDate)<7  -- If day is between sunday and saturday
        If (Select Count(*) From @Holidays Where HDATE=DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0  -- If day is not a holiday
            If @EndDate<@StartDate Return 0 Else Set @WorkMin=DATEDIFF(MI, @StartDate, @EndDate) -- Calculate difference
        Else Return 0
    Else Return 0
End
Else Begin
    Declare @Partial int=1   -- Set partial day flag
    While DateDiff(Day,@StartDate,@EndDate) > 0   -- While start and end days are different
    Begin
        If Datepart(dw,@StartDate)>1 And DATEPART(dw,@StartDate)<7    --  If this is a weekday
        Begin
            If (Select Count(*) From @Holidays Where HDATE=DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0  -- If this is not a holiday
            Begin
                If @Partial=1  -- If this is the first iteration, calculate partial time
                Begin 
                    Set @WorkMin=@WorkMin + DATEDIFF(MI, @StartDate, DateAdd(hour, @EndHour, DateDiff(DAY, 0, @StartDate)))
                    Set @StartDate=DateAdd(hour, @StartHour+24, DateDiff(DAY, 0, @StartDate)) 
                    Set @Partial=0 
                End
                Else Begin      -- If this is a full day, add full minutes
                    Set @WorkMin=@WorkMin + (@EndHour-@StartHour)*60        
                    Set @StartDate = DATEADD(DD,1,@StartDate)
                End
            End
            Else Set (at)StartDate = DATEADD(HOUR, (at)StartHour, CAST(CAST(DATEADD(DD,1,(at)StartDate) AS DATE) AS DATETIME))  
        End
        Else Set (at)StartDate = DATEADD(HOUR, (at)StartHour, CAST(CAST(DATEADD(DD,1,(at)StartDate) AS DATE) AS DATETIME))
    End
    If Datepart(dw,@StartDate)>1 And DATEPART(dw,@StartDate)<7  -- If last day is a weekday
        If (Select Count(*) From @Holidays Where HDATE=DateAdd(dd, DateDiff(dd,0,@StartDate), 0)) = 0   -- And it is not a holiday
            If @Partial=0 Set @WorkMin=@WorkMin + DATEDIFF(MI, @StartDate, @EndDate) Else Set @WorkMin=@WorkMin + DATEDIFF(MI, DateAdd(hour, @StartHour, DateDiff(DAY, 0, @StartDate)), @EndDate)
End 
If @Reverse=1 Set @WorkMin=-@WorkMin
Return @WorkMin

结束

1 个答案:

答案 0 :(得分:0)

使用TIME作为开始时间。然后创建INT变量,将转换后的值放入分钟以用于条件。

我为您创建了示例。

DECLARE @StartDate  DATETIME='2018-12-10 10:00'
DECLARE @ExpectedStartTime  TIME='08:30'

DECLARE @ExpectedStartMin   INT=DATEPART(HOUR,@ExpectedStartTime)*60+DATEPART(MINUTE,@ExpectedStartTime)
DECLARE @ActualStartMin     INT=DATEPART(HOUR,@StartDate)*60+DATEPART(MINUTE,@StartDate)

--Check before change the StartDate
SELECT @ExpectedStartMin, @ActualStartMin, @StartDate


If @ExpectedStartMin<@ActualStartMin Set @StartDate = CAST(CAST(@StartDate AS DATE) AS DATETIME)+@ExpectedStartTime
-- same way to the other conditions.
--
--

--Check after change the StartDate  
SELECT @ExpectedStartMin, @ActualStartMin, @StartDate