在 ruby 中创建两个日期之间的月份范围

问题描述 投票:0回答:10
我需要每月创建一系列月份的日志文件。 因此我需要给定范围内的所有[年,月]元组

如何迭代日期?

如果我需要每天迭代,该怎么办?

ruby date range loops
10个回答
31
投票
例如:

((Date.today - 90)..Date.today).map{|d| [d.year, d.month]}.uniq #=> [[2012, 12], [2013, 1], [2013, 2], [2013, 3]]
    

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]]
    

1
投票
我想出了这个解决方案来生成范围内所有[年,月]元组的列表:

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]]
    

1
投票
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]


    


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


0
投票
这是我写的解决这个问题的方法。 这是专为处理哈希数据而设计的,例如: {星期日,2012年1月1日=>58,星期三,2012年2月1日=>0,星期四,2012年3月1日=>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)


    


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)

 这样的日期,您需要将其转换为该月的第一天


0
投票
我遇到了一个略有不同的问题,但它是相关的:我需要给定的开始和结束之间的月份

def month_start_dates_between_years(start_year, end_year) years = (start_year..end_year).to_a month_tuples = years.product((1..12).to_a) return month_tuples.map { |tuple| Date.new(*tuple) } end
    

0
投票
date1 = Date.new(2024,4,25) date2 = Date.new(2025,2,8) month_distance = 12 * (date2.year - date1.year) + date2.month - date1.month + 1 month_distance.times.map { |m| d = date1 + m.months; [d.year, d.month] } # => [[2024, 4], [2024, 5], [2024, 6], [2024, 7], [2024, 8], [2024, 9], [2024, 10], [2024, 11], [2024, 12], [2025, 1], [2025, 2]]
    

0
投票
一种潜在的单线方法。

(start_date..end_date).to_a.map { |date| date.strftime("%B %Y") }.uniq
    
© www.soinside.com 2019 - 2024. All rights reserved.