2013-03-21 4 views
9

Мне нужно создавать лог-файлы в месяц в течение нескольких месяцев. Для этого мне нужны все [год, месяц] кортежи в заданном диапазонесоздать диапазон месяцев между двумя датами в ruby ​​

Как вы делаете повторение по датам?

Как это можно сделать, если мне нужно будет проходить итерацию каждый день?

+0

Для чего это стоит , если у вас есть доступ к «ActiveSupport» в вашем проекте, «Диапазон» может быть просто расширен для работы с размерами переменных шагов с поддержкой часового пояса (см. http://stackoverflow.com/questions/19093487/ruby-create-range-of -dates/19094504 # ответ-19094504). – captainpete

ответ

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

Это довольно хорошо, но не очень хорошо распространяется на дни, так как месяцы не все имеют одинаковый набор дней, как и месяцы. – dbenhur

1
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

Как это помогает OP повторять по месяцам? – dbenhur

+1

Кроме того, ваш аргумент arg arg и puts не согласуется с именем полученного элемента. – dbenhur

+0

Зачем вызывать 'Time.new.to_date' вместо' Date.new' напрямую? – dbenhur

2

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

Например:

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

«NoMethodError: undefined method 'today' for Date: Class", если вы не требуете 'date'' – dbenhur

+2

Не знаете, почему вы считаете это snark. Многие удивляются, что в '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ', вы получаете после того, как вы' требовали 'даты', и документы делают ужасную работу сообщая вам, когда вам нужно потребовать от stdlib. – dbenhur

0

Вот способ я написал, чтобы решить эту проблему. Это было разработано для работы с данными хэша, например: {Sun, 01 Jan 2012 => 58, Wed, 01 Feb 2012 => 0, Thu, 01 Mar 2012 => 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)

Смежные вопросы