Ruby中有多少个星期一在一段时间内

jhr*_*s21 2 ruby

我有两个DateTime对象(date0date1).

我想知道星期一之间有多少个星期一[date0..date1]

在Ruby中执行此操作的最佳方法是什么?

Aru*_*hit 7

我会用不同的方式,使用Date#uptoArray#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)


bjh*_*aid 5

使用日期#星期一?

[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)

  • 我想你真的想要.count {| X | x.monday?}没有选择,回答OP的问题 (3认同)

Abd*_*bdo 5

@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)