获取两个日期之间唯一的月份和年份数组



我有两个Date对象,例如:

first = Fri, 02 Dec 2016 
last = Wed, 01 Mar 2017

在它们之间获得独特的月份和年份阵列的最有效方法是什么? 在这种情况下,我追求:

Dec 2016
Jan 2017
Feb 2017
Mar 2017
require 'date'
def doit(first, last)
first = first << 1
(12*last.year + last.month - 12*first.year - first.month + 1).
times.map { |i| (first = first >> 1).strftime("%b %Y") }
end
first = Date.parse('Fri, 02 Dec 2016')
last  = Date.parse('Wed, 01 Mar 2017')
doit(first, last)
#=> ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"]

请注意,

(12*last.year + last.month - 12*first.year - first.month + 1)

等于范围涵盖的月数。

您可以创建一个日期数组,然后使用strftime设置正确的格式,并uniq避免重复值,如下所示:

(first..last).map{ |date| date.strftime("%b %Y") }.uniq
#=> ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"]

由于用户要求最有效的方法(只是为了好玩(,以下是所建议解决方案的简单基准:

require 'benchmark'
Benchmark.bmbm(10) do |bm|
bm.report('Cary') do
first = Date.new(1000, 1, 1)
last  = Date.new(2100, 1, 1)
def doit(first, last)
(12*last.year + last.month - 12*first.year - first.month).times.map do
first.strftime("%b %Y")
first = first >> 1
end
end
doit(first, last)
end
bm.report('Simple Lime') do
first = Date.new(1000, 1, 1)
last  = Date.new(2100, 1, 1)
dates = []
while first.beginning_of_month < last.end_of_month
dates << first.strftime("%b %Y")
first = first.next_month
end
end
bm.report('Máté') do
first = Date.new(1000, 1, 1)
last  = Date.new(2100, 1, 1)
(first.beginning_of_month..last).map { |d| d.strftime("%b %Y") if d.day == 1 }.compact
end
bm.report('Gerry/Dan') do
first = Date.new(1000, 1, 1)
last  = Date.new(2100, 1, 1)
(first..last).map{ |date| date.strftime("%b %Y") }.uniq
end
end

结果:

Rehearsal -----------------------------------------------
Cary          0.020000   0.000000   0.020000 (  0.025968)
Simple Lime   0.190000   0.000000   0.190000 (  0.192860)
Máté          0.460000   0.020000   0.480000 (  0.481839)
Gerry/Dan     0.810000   0.020000   0.830000 (  0.835931)
-------------------------------------- total: 1.520000sec
user     system      total        real
Cary          0.020000   0.000000   0.020000 (  0.024871)
Simple Lime   0.150000   0.000000   0.150000 (  0.150696)
Máté          0.390000   0.010000   0.400000 (  0.398637)
Gerry/Dan     0.710000   0.010000   0.720000 (  0.711155)

不是一个漂亮的单行代码,但也不是每天都单独走过,所以对于大范围来说应该会快一点。

first = Date.new(2016, 12, 2)
last = Date.new(2017, 3, 1)
dates = []
while first.beginning_of_month < last.end_of_month
dates << first.strftime("%b %Y")
first = first.next_month
end
puts dates.inspect
# => ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"]

假设这些变量:

first = Date.new(2016, 12, 2)
last = Date.new(2017, 3, 1)

单行解决方案:

(first.beginning_of_month..last).map { |d| d.strftime("%b %Y") if d.day == 1 }.compact
#=> ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"]
start_date=Date.new(2016,12,2)
end_date=Date.new(2017,3,1)
(start_date..end_date).map{ |d| d.strftime("%b %Y") }.uniq
=> ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"] 

最新更新