lib/fat_period/period.rb in fat_period-1.0.3 vs lib/fat_period/period.rb in fat_period-1.1.0

- old
+ new

@@ -27,41 +27,13 @@ # @param last [Date, String] last date of Period # @raise [ArgumentError] if string is not parseable as a Date or # @raise [ArgumentError] if first date is later than last date # @return [Period] def initialize(first, last) - if first.is_a?(Date) - @first = first - elsif first.respond_to?(:to_s) - begin - @first = Date.parse(first.to_s) - rescue ArgumentError => e - if e.message =~ /invalid date/ - raise ArgumentError, "invalid date '#{first}'" - end + @first = Date.ensure_date(first) + @last = Date.ensure_date(last) - raise - end - else - raise ArgumentError, 'use Date or String to initialize Period' - end - - if last.is_a?(Date) - @last = last - elsif last.respond_to?(:to_s) - begin - @last = Date.parse(last.to_s) - rescue ArgumentError => e - if e.message =~ /invalid date/ - raise ArgumentError, "you gave an invalid date '#{last}'" - end - - raise - end - else - raise ArgumentError, 'use Date or String to initialize Period' - end return unless @first > @last raise ArgumentError, "Period's first date is later than its last date" end @@ -581,77 +553,46 @@ size = size.to_sym unless CHUNKS.include?(size) raise ArgumentError, "unknown chunk size '#{size}'" end - if CHUNK_RANGE[size].first > length - return [self] if partial_first || partial_last - - msg = "any #{size} is longer than this period's #{length} days" - raise ArgumentError, msg - end - result = [] chunk_start = first.dup - while chunk_start <= last - case size - when :year - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_year? - end - chunk_end = chunk_start.end_of_year - when :half - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_half? - end - chunk_end = chunk_start.end_of_half - when :quarter - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_quarter? - end - chunk_end = chunk_start.end_of_quarter - when :bimonth - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_bimonth? - end - chunk_end = (chunk_start.end_of_month + 1.day).end_of_month - when :month - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_month? - end - chunk_end = chunk_start.end_of_month - when :semimonth - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_semimonth? - end - chunk_end = chunk_start.end_of_semimonth - when :biweek - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_biweek? - end - chunk_end = chunk_start.end_of_biweek - when :week - unless partial_first - chunk_start += 1.day until chunk_start.beginning_of_week? - end - chunk_end = chunk_start.end_of_week - when :day - chunk_end = chunk_start - else - raise ArgumentError, "invalid chunk size '#{size}'" - end - if chunk_end <= last + chunk_end = chunk_start.end_of_chunk(size) + if chunk_start.beginning_of_chunk?(size) || partial_first + # Keep the first chunk if it's whole or partials allowed + result << Period.new(chunk_start, chunk_end) + chunk_start = chunk_end + 1.day + chunk_end = chunk_start.end_of_chunk(size) + else + # Discard the partial first or move to next whole chunk + chunk_start = chunk_end + 1.day + chunk_end = chunk_start.end_of_chunk(size) + end + # Add Whole chunks + while chunk_end <= last + result << Period.new(chunk_start, chunk_end) + chunk_start = chunk_end + 1.day + chunk_end = chunk_start.end_of_chunk(size) + end + # Possibly append the final chunk to result + if chunk_start < last + if round_up_last result << Period.new(chunk_start, chunk_end) - elsif round_up_last - result << Period.new(chunk_start, chunk_end) elsif partial_last result << Period.new(chunk_start, last) else - break + result end - chunk_start = result.last.last + 1.day + elsif partial_last + # Catch the case where the period is too small to make a whole chunk and + # partial_first is false, so it did not get included as the initial + # partial chunk, yet a partial_last is allowed, so include the whole + # period as a partial chunk. + result << Period.new(first, last) + else + result end - result end # @group Set operations # Is this period contained wholly within or coincident with `other`?