O(1)查找日期范围内的日期,不包括周末

时间:2014-02-26 18:07:09

标签: javascript algorithm date formula

所以,我有两个日期,来自用户界面:

var start = new Date(self.Start()), end = new Date(self.End());

我们需要弄清楚该范围之间的天数,这很容易:

var days = Math.max(0, Math.floor((end - start) / ticksInDay) || 0);

我们使用此数字来计算某种总工作估算值。但是,现在需要这项工作的权力估计不再包括周末。我的第一次尝试是这样的:

var days = Math.max(0, Math.floor((5 / 7) * (end - start) / ticksInDay) || 0);

基本上,如果范围有7天,我们将其乘以(5 / 7)以获得5个实际天数。 14会给我们10个实际日子。但是,这有一些缺陷。

(5/7)*1  = 0.714285714285714
(5/7)*2  = 1.42857142857143
(5/7)*3  = 2.14285714285714
(5/7)*4  = 2.85714285714286
(5/7)*5  = 3.57142857142857
(5/7)*6  = 4.28571428571429
(5/7)*7  = 5
(5/7)*8  = 5.71428571428571
(5/7)*9  = 6.42857142857143
(5/7)*10 = 7.14285714285714
(5/7)*11 = 7.85714285714286
(5/7)*12 = 8.57142857142857
(5/7)*13 = 9.28571428571429
(5/7)*14 = 10

舍入(无论哪种方式)在这里都不起作用,因为3或4天,或10或11天的范围将是错误的。我尝试过的任何其他东西都是丑陋的字符串或如果...... thens 或奇怪的条件陈述。

我能想到的唯一方法是100%准确将循环范围,类似于this answer推荐的方式。但是,只要UI模型发生更改,此代码就必须运行,并且需要计算具有潜在大日期范围的潜在大量行的工作估计值。我担心O(n)解决方案会太慢。

日期范围是否有良好的公式可以排除每7天中的2天?

1 个答案:

答案 0 :(得分:6)

// Count days from d0 to d1 inclusive, excluding weekends
function countWeekDays( d0, d1 )
{
    var ndays = 1 + Math.round((d1.getTime()-d0.getTime())/(24*3600*1000));
    var nsaturdays = Math.floor((ndays + d0.getDay()) / 7);
    return ndays - 2*nsaturdays - (d0.getDay()==0) + (d1.getDay()==6);
}

2014年1月的例子:

    January 2014
Su Mo Tu We Th Fr Sa
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

countWeekDays(new Date(2014,0,1),new Date(2014,0,1)) // 1
countWeekDays(new Date(2014,0,1),new Date(2014,0,2)) // 2
countWeekDays(new Date(2014,0,1),new Date(2014,0,3)) // 3
countWeekDays(new Date(2014,0,1),new Date(2014,0,4)) // 3
countWeekDays(new Date(2014,0,1),new Date(2014,0,5)) // 3
countWeekDays(new Date(2014,0,1),new Date(2014,0,6)) // 4

N.B。 Date输入应该在一天的大致同一时间。如果您仅根据上面的示例创建基于年,月和日的Date个对象,那么您应该没问题。作为一个反例,1月1日上午12点01分到1月2日晚上11:59仅跨越2天,但如果你使用这些时间,上述功能将计为3。