我会用不同的方式,使用Date#upto
和Array#count
:
require 'date'
date1 = Date.parse "01/01/2014"
date2 = Date.parse "01/03/2014"
date1.upto(date2).count(&:monday?) # => 8
Run Code Online (Sandbox Code Playgroud)
使用日期#星期一?
[1] pry(main)> require 'date'
=> true
[2] pry(main)> date1 = "01/01/2014"
=> "01/01/2014"
[3] pry(main)> date2 = "01/03/2014"
=> "01/03/2014"
(Date.parse(date1)..Date.parse(date2)).select { |x| x.monday? }
=> [#<Date: 2014-01-06 ((2456664j,0s,0n),+0s,2299161j)>,
#<Date: 2014-01-13 ((2456671j,0s,0n),+0s,2299161j)>,
#<Date: 2014-01-20 ((2456678j,0s,0n),+0s,2299161j)>,
#<Date: 2014-01-27 ((2456685j,0s,0n),+0s,2299161j)>,
#<Date: 2014-02-03 ((2456692j,0s,0n),+0s,2299161j)>,
#<Date: 2014-02-10 ((2456699j,0s,0n),+0s,2299161j)>,
#<Date: 2014-02-17 ((2456706j,0s,0n),+0s,2299161j)>,
#<Date: 2014-02-24 ((2456713j,0s,0n),+0s,2299161j)>]
Run Code Online (Sandbox Code Playgroud)
上面给出了星期一作为日期对象的列表,但是如果你需要它们的计数那么它是:
mondays = (Date.parse(date1)..Date.parse(date2)).select { |x| x.monday? }
mondays.count
=> 8
Run Code Online (Sandbox Code Playgroud)
对于DateTime
逻辑保持不变
[10] pry(main)> date1 = "01/01/2014"
=> "01/01/2014"
[11] pry(main)> date2 = "01/03/2014"
=> "01/03/2014"
[12] pry(main)> (DateTime.parse(date1)..DateTime.parse(date2)).select { |x| x.monday? }.size
=> 8
Run Code Online (Sandbox Code Playgroud)
@Matt 展示了一个 O(1) 解决方案,这是我的重新实现,并有更多解释:
基本上,为了获取两个日期之间的星期一(或任何其他日期)的数量,我们想要计算从 start_date 到 end_date 的周数并消除几个例外(我将在下面解释)。
Img0:一周中的第几天,0 表示星期日。
获取周数与获取上表中的行数类似。唯一的区别是我们将有一个偏移量,即 start_date 的工作日。
number_of_rows = (day_diff + start_date.wday) / 7 + 1
Run Code Online (Sandbox Code Playgroud)
我们加 1,因为给定两个有效日期,最小行数为 1。
接下来,如果我们的 start_date 的 wday 大于星期几(代码中的 dow),我们不想在行中计算该星期一,因此为 -1。(查看 Img0 进行说明 - 蓝色区域是从星期一之后开始到下星期一之前结束的天数间隔)
同样,如果 end_date 的 wday 小于星期几,我们不想将星期一计入行中。
def day_count(dow, start_date, end_date)
day_diff = (end_date - start_date).to_i
number_of_rows = (day_diff + start_date.wday) / 7 + 1
end_day_index = (day_diff + start_date.wday) % 7
# could have done end_date.wday ; using % 7 to explain
# its existence in @Matt's code
number_of_rows +
( start_date.wday > dow ? -1 : 0 ) +
( end_day_index < dow ? -1 : 0)
end
def monday_count(start_date, end_date)
day_count(1, start_date, end_date)
end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
270 次 |
最近记录: |