我需要每月创建一个月份的日志文件。 因此,我需要在给定范围内的所有[年,月]元组
你如何迭代日期?
如果我每天都需要迭代,怎么办呢?
答案 0 :(得分:28)
例如:
((Date.today - 90)..Date.today).map{|d| [d.year, d.month]}.uniq
#=> [[2012, 12], [2013, 1], [2013, 2], [2013, 3]]
答案 1 :(得分:3)
Ruby Date
支持生成连续几天,并提供next_month
方法,可用于有效地迭代数月。
这是一种适应输入精度的通用方法:
require 'date'
def date_tuples(from,to)
prec = from.size
start = Date.new(*from)
finish = Date.new(*to)
filter_on = [:day,:mon].first(3-prec)
filter = ->(d) { filter_on.all? {|attr| d.send(attr) == 1 } }
(start..finish)
.select(&filter)
.map { |d| [d.year,d.mon,d.day].first(prec) }
end
[7] pry(main)> date_tuples([2012],[2015])
=> [[2012], [2013], [2014], [2015]]
[8] pry(main)> date_tuples([2012,10],[2013,3])
=> [[2012, 10], [2012, 11], [2012, 12], [2013, 1], [2013, 2], [2013, 3]]
[9] pry(main)> date_tuples([2012,10,25],[2012,11,6])
=> [[2012, 10, 25],
[2012, 10, 26],
[2012, 10, 27],
[2012, 10, 28],
[2012, 10, 29],
[2012, 10, 30],
[2012, 10, 31],
[2012, 11, 1],
[2012, 11, 2],
[2012, 11, 3],
[2012, 11, 4],
[2012, 11, 5],
[2012, 11, 6]]
答案 2 :(得分:0)
我想出了这个解决方案来生成范围内所有[年,月]元组的列表:
first=[2012,10]
last=[2013,03]
(first[0]..last[0]).to_a.product((1..12).to_a).select{|ym|(first..last).cover?(ym)}
=> [[2012, 10], [2012, 11], [2012, 12], [2013, 1], [2013, 2], [2013, 3]]
答案 3 :(得分:0)
require 'date'
Time.new(2011).to_date.upto(Time.now.to_date) do |a|
puts ""+a.day.to_s+","+a.month.to_s+","+a.year.to_s
end
或者获得你的月/年元组:
require 'date'
result = []
Time.new(2002).to_date.upto(Time.now.to_date) do |a|
result << [a.month,a.year]
end
result.uniq!
从日期开始使用upto方法:http://ruby-doc.org/stdlib-2.0/libdoc/date/rdoc/Date.html#method-i-upto
答案 4 :(得分:0)
这是我写一篇解决这个问题的方法。 这是为处理哈希数据而设计的,例如: {Sun,2012年1月1日=&gt; 58,Wed,2012年2月1日=&gt; 0,Thu,2012年3月1日=&gt; 0} 但可以很容易地修改数组数据。
请参阅:https://github.com/StephenOTT/add_missing_dates_ruby我提供了一个工作代码示例
但关键的代码是:
def addMissingMonths (datesHash)
count = 0
result = {}
datesHash.keys.each do |x|
if x != datesHash.keys.last
(x+1.month).upto(datesHash.keys[count+1]-1.month) do |a|
result[a.at_beginning_of_month] = 0
end
end
count += 1
end
return result.merge!(datesHash)
end
要查看的关键内容是:(x+1.month).upto(datesHash.keys[count+1]-1.month)
答案 5 :(得分:0)
start_date = 1.year.ago.to_date
end_date = Date.current.yesterday
monthly = [Date.new(start_date.year, start_date.beginning_of_month.month, 1)]
(start_date..end_date).each do |d|
month_date = Date.new(d.year, d.next_month.beginning_of_month.month, 1)
monthly << month_date if monthly.exclude?(month_date) && month_date < end_date - 1.month
end
monthly
=> [Fri, 01 Sep 2017, Sun, 01 Oct 2017, Wed, 01 Nov 2017, Fri, 01 Dec 2017, Sun, 01 Jan 2017, Thu, 01 Feb 2018, Thu, 01 Mar 2018, Sun, 01 Apr 2018, Tue, 01 May 2018, Fri, 01 Jun 2018, Sun, 01 Jul 2018, Wed, 01 Aug 2018]
答案 6 :(得分:0)
这里的大多数答案都需要在范围内每天迭代。这意味着如果您在几年内这样做,您可能会遇到一个包含数千次迭代的循环。
此代码段创建了一个循环,其步骤数与范围内的月份数相同,这样效率更高:
require 'date'
start_date = Date.new(2010, 10)
end_date = Date.new(2011, 4)
current_month = start_date
date_tuples = []
while current_month <= end_date
date_tuples << [current_month.year, current_month.month]
current_month = current_month.next_month
end
pp date_tuples
# => [[2010, 10], [2010, 11], [2010, 12], [2011, 1], [2011, 2], [2011, 3], [2011, 4]]
这种方法的一个怪癖是它只适用于当月第一天的日期。因此,如果您有一个类似 Date.new(2020, 10, 12)
的日期,则需要将其转换为该月的第一天