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

Mik*_*sen 1 javascript algorithm date formula

所以,我有两个日期,来自UI:

var start = new Date(self.Start()), end = new Date(self.End());
Run Code Online (Sandbox Code Playgroud)

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

var days = Math.max(0, Math.floor((end - start) / ticksInDay) || 0);
Run Code Online (Sandbox Code Playgroud)

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

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

基本上,如果范围有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
Run Code Online (Sandbox Code Playgroud)

舍入(无论哪种方式)在这里都不起作用,因为3或4天或10或11天的范围将是错误的.我尝试过的任何其他内容都等于一个丑陋的字符串或者如果......或者奇怪的条件语句.

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

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

Mat*_*att 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);
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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