简体   繁体   中英

Get last X month names in Rails

I'm trying to get an array of month names from the last 6 months. I've seen other posts that address iterating and printing actual dates 7/1/16, 7/2/16, etc., but nothing that just does month names:

["February", "March", "April", "May", "June" ,"July"]

I was trying the following code, but I get this error:

@array = []
(6.months.ago..Time.now).each do |m|
  @array.push(Date::MONTHNAMES[m])  
end 

TypeError: can't iterate from ActiveSupport::TimeWithZone

A slightly uglier version that builds on Olives' answer , but doesn't require looking up dates in each month and is about 31x faster:

current_month = Date.today.month

month_names = 6.downto(1).map { |n| DateTime::MONTHNAMES.drop(1)[(current_month - n) % 12] }

Output when current_month is 4 (to test Dec-Jan rollover):

["November", "December", "January", "February", "March", "April"] 

Benchmark:

Benchmark.measure do
  10000.times do
    current_month = Date.today.month
    month_names = 6.downto(1).map { |n| DateTime::MONTHNAMES.drop(1)[(current_month - n) % 12] }
  end
end
=> #<Benchmark::Tms:0x007fcfda4830d0 @label="", @real=0.12975036300485954, @cstime=0.0, @cutime=0.0, @stime=0.07000000000000006, @utime=0.06999999999999984, @total=0.1399999999999999> 

Compare to the cleaner version:

Benchmark.measure do
  10000.times do
    5.downto(0).collect do |n| 
        Date::MONTHNAMES[n.months.ago.month]
    end
  end
end
=> #<Benchmark::Tms:0x007fcfdcbde9b8 @label="", @real=3.7730263769917656, @cstime=0.0, @cutime=0.0, @stime=0.04999999999999993, @utime=3.69, @total=3.7399999999999998> 

A simple, although a bit naive way, would be to iterate over integers and calculate which month it falls into and then finally look it up in the array.

5.downto(0).collect do |n| 
  Date::MONTHNAMES[n.months.ago.month]
end

This will return ["February", "March", "April", "May", "June", "July"] (This is being executed in July)

Below Version will display in 3 character month format:

5.downto(0).collect do |n| 
  Date.parse(Date::MONTHNAMES[n.months.ago.month]).strftime('%b')
end

Output: (considering current month as January)

["Aug", "Sep", "Oct", "Nov", "Dec", "Jan"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM