Gappodi
Gappodi

Reputation: 33

How to get start and end dates from a time/date object created using a month or year in ruby?

I have ISO 8601 compliant date strings like "2016" or "2016-09" representing year or months. How can I get start end dates from this.

for example:

2016    -> ["2016-01-01", "2016-12-31"]
2016-09 -> ["2016-09-01", "2016-09-30"]

Thank you

Upvotes: 3

Views: 78

Answers (3)

Oleksandr Holubenko
Oleksandr Holubenko

Reputation: 4440

One more solution in according to @AndreyDeineko :)

require 'date'

def create_date date
  date = date.split('-').map(&:to_i)
  [Date.new(*date, 1, 1), Date.new(*date, -1, -1)].map(&:to_s)
end

Upvotes: 2

akuhn
akuhn

Reputation: 27813

Try this

require 'date'

def iso8601_range(str)
  parts = str.scan(/\d+/).map(&:to_i)
  date = Date.new(*parts)
  case parts.size
  when 1
    date .. date.next_year - 1
  when 2
    date .. date.next_month - 1
  else
    date .. date
  end

end

iso8601_range('2016') # => 2016-01-01..2016-12-31
iso8601_range('2016-09') # => 2016-09-01..2016-09-30
iso8601_range('2016-09-20') # => 2016-09-20..2016-09-20

If you are cool with using send you can replace the case statement with

date .. date.send([:next_year,:next_month,:next_day][parts.size - 1]) - 1

Upvotes: 4

Andrey Deineko
Andrey Deineko

Reputation: 52367

require 'date'

def create_start_end(string)
  year, month = string.split('-').map(&:to_i)
  if month && !month.zero?
    [Date.new(year, month, 1).to_s, Date.new(year, month, -1).to_s]
  else
    [Date.new(year, 1, 1).to_s, Date.new(year, 12, -1).to_s]
  end
end

create_start_end('2016')
#=> ["2016-01-01", "2016-12-31"]
create_start_end('2016-01')
#=> ["2016-01-01", "2016-01-31"]
create_start_end('2016-09')
#=> ["2016-09-01", "2016-09-30"]

Upvotes: 2

Related Questions