2013-03-21 16 views
9

Ho bisogno di creare file di log al mese per un intervallo di mesi. Quindi ho bisogno di tutte le tuple [anno, mese] in un determinato intervallocreare un intervallo di mesi tra due date in rubino

Come si fa a ripetere le date?

Come si può fare se ho bisogno di iterare ogni giorno?

+0

Per quel che vale , se hai accesso a 'ActiveSupport' nel tuo progetto' Range' può essere semplicemente esteso per lavorare con dimensioni a step variabile con supporto timezone (vedi http://stackoverflow.com/questions/19093487/ruby-create-range-of -dates/19094504 # risposta-19094504). – captainpete

risposta

0

sono arrivato fino a questa soluzione per generare un elenco di tutti i [anno, mese] tuple nella gamma:

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

Questo è abbastanza bello, ma non si estende piacevolmente ai giorni in quanto i mesi non hanno tutti la stessa serie di giorni di anni di mesi. – 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 

o di ottenere il tuo mese/anno tuple:

require 'date' 
result = [] 
Time.new(2002).to_date.upto(Time.now.to_date) do |a| 
    result << [a.month,a.year] 
end 
result.uniq! 

Utilizzare il metodo upto dalla data: http://ruby-doc.org/stdlib-2.0/libdoc/date/rdoc/Date.html#method-i-upto

+0

In che modo questo aiuta OP a scorrere di mesi? – dbenhur

+1

Inoltre, la dichiarazione del blocco e della dichiarazione di blocco non è d'accordo sul nome dell'elemento ceduto. – dbenhur

+0

Perché chiamare 'Time.new.to_date' invece di' Date.new' direttamente? – dbenhur

2

Ruby Date supporta produzione giorni successivi e offre un metodo next_month che potrebbe essere utilizzato per iterare in modo efficiente per mesi.

Ecco un metodo generico che si adatta alla precisione di ingressi:

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

Ad esempio:

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

"NoMethodError: metodo non definito 'today' per Date: Class" a meno che tu non richieda 'date'' – dbenhur

+2

Non sai perché consideri questo snark. Molte persone sono sorprese che ci sia un built-in classe "Date" fuori dalla scatola in "irb" o "pry" che è un'ombra paralizzata del "Date" che si ottiene dopo aver richiesto "date" e che i documenti fanno un lavoro terribile ti dice quando è necessario richiedere da stdlib. – dbenhur

0

Ecco un modo ho scritto per risolvere questo problema. Questo è stato progettato per lavorare con dati hash come: {Dom, 01 gen 2012 => 58, mer, 01 feb 2012 => 0, gio, 01 mar 2012 => 0} ma potrebbe essere facilmente modificato per dati array.

See: https://github.com/StephenOTT/add_missing_dates_ruby dove ho fornito un esempio di codice di lavoro

Ma il pezzo chiave di codice è:

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 

Il contenuto chiave da guardare è: (x+1.month).upto(datesHash.keys[count+1]-1.month)

Problemi correlati