Calculate business hours between two dates

前端 未结 14 1288
被撕碎了的回忆
被撕碎了的回忆 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:39

    Here is an inline version Start/EndDateTime like 2015-03-16 09:52:24.000 Start/EndTime (businesshours) like 07:00:00 It is bulky but works in your select statement

    I will post it in Function version as well.

    Case when  =  then 0
        When Convert(date,) = Convert(date,) Then 
             IIF( DATEPART(Dw,)  in(1,7)
                      or Convert(time,) > Convert(time,)
                      or Convert(time,) < Convert(time,),0, 
            DateDiff(S,IIF(Convert(time,) < Convert(time,),Convert(time,),Convert(time,))
                    ,IIF(Convert(time,) > Convert(time,), Convert(time,), Convert(time,))))
        when  Convert(date,) <> Convert(date,) then 
            IIF(DATEPART(Dw,) in(1,7) or Convert(time,) >  Convert(time,),0 ,DateDiff(S,IIF(Convert(time,) < Convert(time,),Convert(time,),Convert(time,)), Convert(time,)))
            + IIF(DATEPART(Dw,) in(1,7) or  Convert(time,) <  Convert(time,),0,DateDiff(S,Convert(time,),IIF(Convert(time,) > Convert(time,), Convert(time,), Convert(time,))))
        else -333
        end --as pday
    
    +IIF(DatePart(wEEk,)  = DatePart(wEEk,) 
    ,0, (DateDiff(wk,dateadd(d,-datepart(dw,),dateadd(ww,1,)),DATEADD(wk, DATEDIFF(wk, 6, ), 6)-1) * 5)) * Datediff(S, Convert(time,),Convert(time,)) --Fullweek_days
    
    +Case When Convert(date,) = Convert(date,) then 0
          When DatePart(wEEk,)  <> DatePart(wEEk,) then
                            IIF( datepart(dw,) = 7,0,DateDIFF(DAY,+1,dateadd(d,-datepart(dw,),dateadd(ww,1,))))  -- beginFulldays
                            +IIF( datepart(dw,) = 1,0,DateDIFF(DAY,DATEADD(wk, DATEDIFF(wk, 6, ), 6), -1))  --Endfulldays
          When DatePart(wEEk,)  = DatePart(wEEk,) then
                DateDiff(DAY,+1, ) 
        ELSE -333 END * Datediff(S, Convert(time,),Convert(time,))    
    

    Here is the Function Version:

    CREATE FUNCTION [dbo].[rsf_BusinessTime]
    (
    @startDateTime Datetime,
    @endDateTime Datetime ,
    @StartTime VarChar(12),
    @EndTime VarChar(12) )
    RETURNS BIGINT
    As
    BEGIN
    Declare @totalSeconds BigInt,
        @SecondsInDay int,
        @dayStart Time = Convert(time,@StartTime),
        @dayEnd Time =Convert(time,@EndTime),
        @SatAfterStart Datetime = dateadd(d,-datepart(dw,@startDateTime),dateadd(ww,1,@startDateTime)), 
        @Sunbeforend Datetime = DATEADD(wk, DATEDIFF(wk, 6, @endDateTime), 6) 
    
    -- This function calculates the seconds between the start and end dates provided for business hours. 
    -- It only returns the time between the @start and @end time (hour of day) of the work week. 
    -- Weekend days are removed.
    -- Holidays are not considered.  
    
    Set @SecondsInDay = Datediff(S, @dayStart,@dayEnd) 
    
    
    Set @totalSeconds = 
     --first/last/sameday
        Case when  @startDateTime= @endDateTime then 0
        When Convert(date,@startDateTime) = Convert(date,@endDateTime) Then 
             IIF( DATEPART(Dw,@startDateTime)  in(1,7)
                      or Convert(time,@startDateTime) > @dayEnd
                      or Convert(time,@endDateTime) < @dayStart,0, 
            DateDiff(S,IIF(Convert(time,@startDateTime) < @dayStart,@dayStart,Convert(time,@startDateTime))
                    ,IIF(Convert(time,@endDateTime) > @dayEnd, @dayEnd, Convert(time,@endDateTime))))
        when  Convert(date,@startDateTime) <> Convert(date,@endDateTime) then 
            IIF(DATEPART(Dw,@startDateTime) in(1,7) or Convert(time,@startDateTime) >  @dayEnd,0 ,DateDiff(S,IIF(Convert(time,@startDateTime) < @dayStart,@dayStart,Convert(time,@startDateTime)), @dayEnd))
            + IIF(DATEPART(Dw,@endDateTime) in(1,7) or  Convert(time,@endDateTime) <  @dayStart,0,DateDiff(S,@dayStart,IIF(Convert(time,@endDateTime) > @dayEnd, @dayEnd, Convert(time,@endDateTime))))
        else -333
        end --as pday
    
    +IIF(DatePart(wEEk,@startDateTime)  = DatePart(wEEk,@endDateTime)   
    ,0, (DateDiff(wk,@SatAfterStart,@Sunbeforend-1) * 5)) * @SecondsInDay --Fullweek_days
    
    +Case When Convert(date,@startDateTime) = Convert(date,@endDateTime) then 0
          When DatePart(wEEk,@startDateTime)  <> DatePart(wEEk,@endDateTime) then
                            IIF( datepart(dw,@startDateTime) = 7,0,DateDIFF(DAY,@startDateTime+1,@SatAfterStart))  -- beginFulldays
                            +IIF( datepart(dw,@endDateTime) = 1,0,DateDIFF(DAY,@Sunbeforend,@endDateTime -1))  --Endfulldays
          When DatePart(wEEk,@startDateTime)  = DatePart(wEEk,@endDateTime) then
                DateDiff(DAY,@startDateTime+1,@endDateTime ) 
        ELSE -333 END * @SecondsInDay
    
    
    Return @totalSeconds
    END 
    

提交回复
热议问题