Skip to content

Instantly share code, notes, and snippets.

@ziaulrehman40
Created August 3, 2019 11:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ziaulrehman40/cb1d57ab44597305397cd0c1a9eabaaa to your computer and use it in GitHub Desktop.
Save ziaulrehman40/cb1d57ab44597305397cd0c1a9eabaaa to your computer and use it in GitHub Desktop.
Simple ruby date range splitter
class DateRangeSplitter
include Enumerable
def initialize(date_from, date_to, max_days, end_inclusive: true)
@date_from = date_from
@date_to = date_to
@max_days = max_days
@end_inclusive = end_inclusive
generate_split_dates
end
def each
return enum_for(:each) unless block_given?
@dates.each { |date_block| yield(date_block[0], date_block[1]) }
end
private
def generate_split_dates
start_date = @date_from
@dates = []
begin
end_date = start_date + (@end_inclusive ? @max_days - 1 : @max_days).days
if end_date <= @date_to
@dates << [start_date, end_date]
else
@dates << [start_date, @date_to]
break
end
start_date = @end_inclusive ? end_date + 1.day : end_date
end while start_date <= @date_to
@dates
end
end
@mollerhoj
Copy link

mollerhoj commented Jan 24, 2021

As mentioned in this thread: https://stackoverflow.com/questions/9795391/is-there-a-standard-for-inclusive-exclusive-ends-of-time-intervals We should prefer inclusive start dates and exclusive end dates.

We can split a DateRange into days, weeks, months or years with the following tail recursive method:

  class DateRange
    def initialize(since_date, until_date)
      @since_date = since_date
      @until_date = until_date
    end

    def split_to(timespan)
      return [] if @since_date == @until_date
      end_date = [@since_date.send("next_#{timespan.to_s.singularize}"), @until_date].min
      [DateRange.new(@since_date, end_date)] + DateRange.new(end_date, @until_date).split_to(timespan)
    end
  end

This method takes :days, :weeks, :months or :years as a parameter. Notice that we rely on activesupport.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment