如何计算两个日期之间的分钟数,不包括周末和假日?

时间:2017-04-26 11:17:20

标签: sql-server

如何计算SQL Server 2008R2中表格(从第1行到结尾)的两个日期之间的分钟计数(分钟计算是星期一上午7点到星期五下午7点)?

我试过这样的东西,但它不起作用

     DECLARE  @StartDate DateTime='2015-06-12 13:03:00'
     DECLARE @EndDate DateTime='2015-06-16 10:08:00'

        IF DATEPART(WEEKDAY,@StartDate) = 1
            SET @StartDate = DATEADD(HOUR,8,DATEADD(DAY,DATEDIFF(DAY,0,@StartDate),1))
        IF DATEPART(WEEKDAY,@StartDate) = 7
            set @StartDate = DATEADD(HOUR,8,DATEADD(DAY,DATEDIFF(DAY,0,@StartDate),2))


        IF DATEPART(WEEKDAY,@EndDate) = 1
            SET @EndDate = DATEADD(HOUR,19,DATEADD(DAY,DATEDIFF(DAY,0,@EndDate),-2))
        IF DATEPART(WEEKDAY,@EndDate) = 7
            SET @EndDate = DATEADD(HOUR,19,DATEADD(DAY,DATEDIFF(DAY,0,@EndDate),-1))

        IF DATEPART(WEEKDAY,@StartDate) = 2 AND DATEPART(HH, @StartDate)<8
            SET @StartDate = DATEADD(HOUR, 8, DATEDIFF(DAY, 0, @StartDate))
        IF DATEPART(WEEKDAY,@EndDate) = 6 AND DATEPART(HH, @EndDate)>8
            SET @EndDate = DATEADD(HOUR, 19, DATEDIFF(DAY, 0, @EndDate)) 

    Declare @WorkMin int  
    Set @WorkMin=DATEDIFF(MI,@StartDate,@EndDate)-(DATEDIFF(WEEK,@StartDate,@EndDate)*2880)

    Print @WorkMin ----Out put is 2705

    ---------Actual Minutes is 1985

以上代码是在星期五晚上7点和星期一早上7点之前计算分钟数。但我想排除那些分钟。所以有人可以帮我这个吗?

2 个答案:

答案 0 :(得分:0)

我得到1985分钟。老实说,我第一次按照你的规则编写脚本时得到了这个,我觉得这很奇怪。

--Working week is 7AM Monday to 7PM Friday
--Get the start date
DECLARE @StartDate DATETIME = '20150612 13:03:00';

--If the start date is in the weekend period then move it forward to 7AM Monday
DECLARE @days INT = NULL;
IF DATEPART(WEEKDAY, @StartDate) = 7 --Saturday
    SELECT @days = 2;
IF DATEPART(WEEKDAY, @StartDate) = 1 --Sunday
    SELECT @days = 1;
IF DATEPART(WEEKDAY, @StartDate) = 6 AND DATEPART(HOUR, @StartDate) > 19 --Friday after 7PM
    SELECT @days = 3;
IF DATEPART(WEEKDAY, @StartDate) = 2 AND DATEPART(HOUR, @StartDate) < 7 --Monday before 7AM
    SELECT @days = 0;
IF @days IS NOT NULL
    SELECT @StartDate = CONVERT(DATETIME, DATEPART(YEAR, DATEADD(DAY, @days, @StartDate)) + DATEPART(MONTH, DATEADD(DAY, @days, @StartDate)) + DATEPART(DAY, DATEADD(DAY, @days, @StartDate)) + ' 07:00');

--Get the end date
DECLARE @EndDate DATETIME = '20150616 10:08:00';

--If the end date is in the weekend period then move it back to 7PM Friday
SELECT @days = NULL;
IF DATEPART(WEEKDAY, @EndDate) = 7 --Saturday
    SELECT @days = -1;
IF DATEPART(WEEKDAY, @EndDate) = 1 --Sunday
    SELECT @days = -2;
IF DATEPART(WEEKDAY, @EndDate) = 6 AND DATEPART(HOUR, @EndDate) > 19 --Friday after 7PM
    SELECT @days = 0;
IF DATEPART(WEEKDAY, @EndDate) = 2 AND DATEPART(HOUR, @EndDate) < 7 --Monday before 7AM
    SELECT @days = -3;
IF @days IS NOT NULL
    SELECT @EndDate = CONVERT(DATETIME, DATEPART(YEAR, DATEADD(DAY, @days, @EndDate)) + DATEPART(MONTH, DATEADD(DAY, @days, @EndDate)) + DATEPART(DAY, DATEADD(DAY, @days, @EndDate)) + ' 19:00');

--Now calculate the raw minutes
DECLARE @Minutes INT;
SELECT @Minutes = DATEDIFF(MINUTE, @StartDate, @EndDate);

--Work out how many complete weeks we have, then take this off the result
DECLARE @CompleteWeeks INT = 0;
SELECT @CompleteWeeks = DATEDIFF(WEEK, @StartDate, @EndDate);
SELECT @Minutes = @Minutes - @CompleteWeeks * DATEDIFF(MINUTE, '20170421 19:00', '20170424 07:00'); --3600 minutes, we could just hardcode this

--Output
SELECT 'Start Date' AS metric, CONVERT(VARCHAR(50), @StartDate) AS [value]
UNION ALL
SELECT 'End Date', CONVERT(VARCHAR(50), @EndDate)
UNION ALL
SELECT 'Minutes', CONVERT(VARCHAR(50), @Minutes);

可能有更好的方法可以做到这一点,但我基本上把问题分解为这些步骤:

  • 如果开始日期在&#34;周末期间&#34;然后将其推进到周一早上7点;
  • 如果结束日期在&#34;周末期间&#34;然后将其向后移至星期五晚上7点;
  • 计算调整日期之间的分钟数;
  • 删除&#34;周末期&#34;我们在日期范围内留下的每个完整周的分钟数(即星期五晚上7点到星期一早上7点的分钟数)。由于我之前的调整,这应该有效。

我不确定开始/结束位是否正常工作,因为您的示例日期不是很好的示例(它们都不是在周末期间)。

我尝试按照与您的脚本类似的模式(从根本上说它没有工作)。

答案 1 :(得分:0)

有些东西不匹配。根据我的计算,该值为1265分钟: manual excel calculation

产生的代码(没有总结)如下。它基于日历表的一个非常具体的版本 - 这是一种你应该学习如何融入你的技能组的技巧。它是静态定义的,包含足够的信息来证明这个特定的问题;我将把它留给你以更通用的方式进行调整。

set nocount on;
declare @cal table (dt_start datetime not null, dt_end datetime not null); 
insert @cal(dt_start, dt_end) values 
('20150611 07:00', '20150611 19:00'), 
('20150612 07:00', '20150612 19:00'), -- friday
('20150615 07:00', '20150615 19:00'), 
('20150616 07:00', '20150616 19:00'), 
('20150617 07:00', '20150617 19:00'),
('20150618 07:00', '20150618 19:00');
select * from @cal order by dt_start;

declare @ps datetime, @pe datetime; 
set @ps = '20150612 13:03';
set @pe = '20150616 10:08';
select @ps as ps, @pe as pe; 

select --@ps as [start], @pe as [end], 
t.*, 
case when t.dt_start < @ps then @ps else t.dt_start end as s1, 
case when t.dt_end > @pe then @pe else t.dt_end end as e1,
datediff(minute, 
case when t.dt_start < @ps then @ps else t.dt_start end,   
case when t.dt_end > @pe then @pe else t.dt_end end ) as calc
from @cal as t
where t.dt_start <= @pe and t.dt_end >= @ps
order by t.dt_start
;

你首先说你的工作时间是早上7点到晚上7点,但你后来说是早上8点到晚上7点。我仍然不太清楚你的计算是如何运作的,但使用8am的一小时差异并不能解释这种差异。