2013-03-21 18 views
9

Tôi cần tạo nhật ký mỗi tháng trong một phạm vi tháng. Do đó, tôi cần tất cả các bộ dữ liệu [năm, tháng] trong một phạm vi nhất địnhtạo một phạm vi tháng giữa hai ngày trong ruby ​​

Làm cách nào để lặp lại qua các ngày?

Làm cách nào để thực hiện điều này nếu tôi cần lặp lại hàng ngày?

+0

Đối với những gì nó có giá trị , nếu bạn có quyền truy cập vào 'ActiveSupport' trong dự án của bạn' Phạm vi' có thể được mở rộng đơn giản để làm việc với các kích thước bước biến với hỗ trợ múi giờ (xem http://stackoverflow.com/questions/19093487/ruby-create-range-of -dates/19094504 # answer-19094504). – captainpete

Trả lời

0

tôi đã đưa ra giải pháp này để tạo ra một danh sách tất cả các bộ [năm, tháng] trong khoảng:

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

Điều này là khá tốt đẹp, nhưng không độc đáo kéo dài đến ngày như tháng không phải tất cả có cùng một bộ ngày như năm tháng. – 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 

Hoặc nhận được tháng/năm tuples của bạn:

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

Sử dụng phương pháp tối đa từ ngày: http://ruby-doc.org/stdlib-2.0/libdoc/date/rdoc/Date.html#method-i-upto

+0

Điều này giúp OP lặp đi lặp lại theo tháng như thế nào? – dbenhur

+1

Ngoài ra, khối arg của bạn và đặt tuyên bố không đồng ý về tên của yếu tố mang lại. – dbenhur

+0

Tại sao gọi 'Time.new.to_date' thay vì' Date.new' trực tiếp? – dbenhur

2

Ruby Date hỗ trợ sản xuất những ngày kế tiếp và cung cấp phương thức next_month có thể được sử dụng để lặp lại hiệu quả qua nhiều tháng.

Dưới đây là một phương pháp chung mà thích nghi với độ chính xác của đầu vào của bạn:

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

Ví dụ:

((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' cho Date: Class" trừ khi bạn 'require 'date'' – dbenhur

+2

Không chắc chắn lý do tại sao bạn xem xét snark này. Nhiều người ngạc nhiên rằng có một lớp 'Date' được tạo sẵn trong' irb' hoặc 'pry' là một cái bóng bị tê liệt của' Date' mà bạn nhận được sau khi bạn 'yêu cầu 'date'' và các tài liệu làm một công việc khủng khiếp nói với bạn khi bạn cần yêu cầu từ stdlib. – dbenhur

0

Dưới đây là một cách tôi đã viết để giải quyết vấn đề này. Điều này được thiết kế để làm việc với dữ liệu băm như: {Sun, 01 Jan 2012 => 58, Wed, 01 Feb 2012 => 0, Thu, 01 Mar 2012 => 0} nhưng có thể dễ dàng sửa đổi cho dữ liệu mảng.

Xem: https://github.com/StephenOTT/add_missing_dates_ruby nơi mà tôi đã cung cấp một mẫu mã làm việc

Nhưng mảnh chìa khóa mã là:

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 

Nội dung quan trọng để xem xét là: (x+1.month).upto(datesHash.keys[count+1]-1.month)