2012-12-16 13 views
8

Ruby on Rails uygulamasında birkaç ay içinde dönmem gerekiyor. Her ay için, o ayın ilk ve son gününü bulmam gerek. Bu tarihler daha sonra bu tarihler boyunca meydana gelen olayları bulmak ve bunlarda hesaplamalar yapmak için ayrı bir sorguda kullanılır. TabiiRuby on Rails'de Aylara Nasıl Dönülür

(11.months.ago.to_date.month..Date.today.month).each do |m| 
    start_date = '01-#{m}-#{Date.today.year}'.to_date.beginning_of_month 
    end_date = '01-#{m}-#{Date.today.year}'.to_date.end_of_month 
end 

, yıl 11 ay önce önceki yıla geçmeyi içerir durumunda bu durumda güncelleştirilmiş değildir:

Başlangıçta, ben böyle bir şey denedim. Ve, bu tür için/her döngü çalışır sanmıyorum. Sayıları bir diziye eşleştirip aynı yöntemi kullanarak denedim, ancak bir hata aldı.

Böyle bir şeyi başarmanın en iyi yolu nedir?

+0

Eğer keyfi başlangıç ​​/ bitiş tarihlerini bekliyor musunuz? – Substantial

cevap

10

Birincisi, iki tarih arasındaki ay sayısını (Massimiliano Peluso ait nezaket) saymak:

start_date = 13.months.ago.to_date 
# => Wed, 16 Nov 2011 

end_date = Date.today 
# => Sun, 16 Dec 2012 

number_of_months = (end_date.year*12+end_date.month)-(start_date.year*12+start_date.month) 
# => 13 

Ardından, başlangıç ​​ayından itibaren, her ay eafter, ilk/son tarihleri ​​bulun ve bir biriktirici dizisine ekleyin.

dates = number_of_months.times.each_with_object([]) do |count, array| 
    array << [start_date.beginning_of_month + count.months, 
      start_date.end_of_month + count.months] 
end 
# => ... 

Şimdi dates her ayın ilk ve son tarihine karşılık gelen iç içe Date çiftleri içeren bir dizi içerecektir. Bu dates dizisi işlemek için yineleme yapmak kolay olacak.

dates 
# => [[Tue, 01 Nov 2011, Wed, 30 Nov 2011], [Thu, 01 Dec 2011, Fri, 30 Dec 2011], ... 

dates[0].first 
# => Tue, 01 Nov 2011 

dates[0].last 
# => Wed, 30 Nov 2011 

dates[0].last.class 
# => Date 

Bu test edilir ve Raylar 3.2.5/Ruby çalışan 1.9.3p194

+0

teşekkürler - Bu en iyi açıklama olduğunu düşündüm ve benim durumumda uygulamak için en temiz yol oldu (aynı zamanda yıllarca ayarlanmış). – Justin

+0

'Fri, 30 Aralık 2011' Aralık'ın son günü değil – MikDiet

12

İşte bunu yapmak için bir yol var:

number_of_months = 0..11 
number_of_months.to_a.reverse.each do |month_offset| 
    start_date = month_offset.months.ago.beginning_of_month 
    end_date = month_offset.months.ago.end_of_month 
    puts "Start date : #{start_date} End date : #{end_date}" 
end 

=>

Start date : 2012-01-01 00:00:00 -0700 End date : 2012-01-31 23:59:59 -0700 
Start date : 2012-02-01 00:00:00 -0700 End date : 2012-02-29 23:59:59 -0700 
Start date : 2012-03-01 00:00:00 -0700 End date : 2012-03-31 23:59:59 -0600 
Start date : 2012-04-01 00:00:00 -0600 End date : 2012-04-30 23:59:59 -0600 
Start date : 2012-05-01 00:00:00 -0600 End date : 2012-05-31 23:59:59 -0600 
Start date : 2012-06-01 00:00:00 -0600 End date : 2012-06-30 23:59:59 -0600 
Start date : 2012-07-01 00:00:00 -0600 End date : 2012-07-31 23:59:59 -0600 
Start date : 2012-08-01 00:00:00 -0600 End date : 2012-08-31 23:59:59 -0600 
Start date : 2012-09-01 00:00:00 -0600 End date : 2012-09-30 23:59:59 -0600 
Start date : 2012-10-01 00:00:00 -0600 End date : 2012-10-31 23:59:59 -0600 
Start date : 2012-11-01 00:00:00 -0600 End date : 2012-11-30 23:59:59 -0700 
Start date : 2012-12-01 00:00:00 -0700 End date : 2012-12-31 23:59:59 -0700 
+0

Evet, bu '' ruby ​​1.8.7''de ray 3.0.10' ile –

6
time_start = 13.months.ago 
time_end = 0.seconds.ago 
time = time_start 
while time < time_end 
    puts("m:#{time.month} y:#{time.year}") 
    time = time.advance(months: 1) 
end 
+0

Eh' 'Date.advance'' yöntemi artık mevcut görünmüyor. 1 ay içinde ilerlemek için '' Date.next_month'' ya da '' mydate >> 1'' kullanabilirsiniz. Http://www.ruby-doc.org/stdlib-2.1.2/libdoc/date/rdoc/Date.html#method-i-next_month –

+0

Veya 'time + = 1.month' – jonnysamps

6
(start_date..end_date).select{|date| date.day == 1}.map{|date| [date.beginning_of_month, date.end_of_month]}