我有两个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"]