app/jobs/reports/month_helper.rb
# frozen_string_literal: true
module Reports
module MonthHelper
module_function
# Takes a date range and breaks it into an array of ranges by month. The first and last items
# may be partial months (ex starting in the middle and ending at the end) and the intermediate
# items are always full months (1st to last of month)
# @example
# months(Date.new(2021, 3, 15)..Date.new(2021, 5, 15))
# => [
# Date.new(2021, 3, 15)..Date.new(2021, 3, 31),
# Date.new(2021, 4, 1)..Date.new(2021, 4, 30),
# Date.new(2021, 5, 1)..Date.new(2021, 5, 15),
# ]
# @param [Range<Date>] date_range
# @return [Array<Range<Date>>]
def months(date_range)
return [date_range] if start_end_same_month?(date_range)
results = []
results << (date_range.begin..date_range.begin.end_of_month)
current = date_range.begin.end_of_month + 1.day
while current < date_range.end.beginning_of_month
month_start = current.beginning_of_month
month_end = current.end_of_month
results << (month_start..month_end)
current = month_end + 1.day
end
results << (date_range.end.beginning_of_month..date_range.end) if current < date_range.end
results
end
# @api private
def start_end_same_month?(date_range)
start_date = date_range.begin
end_date = date_range.end
start_date.year == end_date.year && start_date.month == end_date.month
end
end
end