Вопрос

I have a Ruby date range: range = Date.parse("February 1, 2013")..Date.parse("January 15, 2014")

If you do range.to_a and convert it to an array, you get array items of every single day in that range.

What I want is an array of the last day of each month.

Basically something like: [2013-02-28, 2013-03-31, 2013-04-30, ..., 2013-12-31, 2014-01-31]

Это было полезно?

Решение

Here's one way, off the top of my head:

range = Date.parse("February 1, 2013")..Date.parse("January 15, 2014")
range.to_a.map {|date| Date.new(date.year,date.month,1)}.uniq.map {|date| date.next_month.prev_day}

Or in other words:

For every date in the array

  1. Make the day element equal to 1 to find the first of each month ...
  2. Make the set unique, so you have one element per month ...
  3. Add one month to each value ...
  4. Subtract one day.

Другие советы

A negative day-of-month counts backwards, so -1 is the last day of the month:

require 'date'

def last_days_of_months(year=Date.today.year)
  (1..12).map{|month| Date.new(year, month, -1)}
end

puts last_days_of_months

Output:

2014-01-31
2014-02-28
2014-03-31
2014-04-30
2014-05-31
2014-06-30
2014-07-31
2014-08-31
2014-09-30
2014-10-31
2014-11-30
2014-12-31
require 'date'
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def days_in_month(month, year = Time.now.year)
   return 29 if month == 2 && Date.gregorian_leap?(year)
   COMMON_YEAR_DAYS_IN_MONTH[month]
end

range = Date.parse("February 1, 2013")..Date.parse("January 15, 2014")
last_year = range.last.year
last_month = range.last.month
last_day =  Time.new(last_year, last_month, days_in_month(last_month, last_year)).to_date

range.select { |d| d.day == days_in_month(d.month, d.year) }.push(last_day).map(&:to_s)
 # => ["2013-02-28", "2013-03-31", "2013-04-30", "2013-05-31", "2013-06-30", "2013-07-31", "2013-08-31", "2013-09-30", "2013-10-31", "2013-11-30", "2013-12-31", "2014-01-31"]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top