lib/roxbury/business_calendar.rb in roxbury-0.1.0 vs lib/roxbury/business_calendar.rb in roxbury-0.1.1

- old
+ new

@@ -53,25 +53,38 @@ # @param to [Date, Time] # @param number_of_days [Integer, Float] # @return [Date, Time] The result of adding the number_of_days to the given date. If a Date is given returns a Date, otherwise if a Time is given returns a Time. def add_working_days to, number_of_days - result = add_working_hours(to, number_of_days * max_working_hours_in_a_day) - to.is_a?(Date) ? result.to_date : result + raise ArgumentError, 'number_of_days must not be negative' if number_of_days < 0 + + if to.is_a?(Time) + # this implementation would work for Date instances as well, but is around 10 times slower than the other in my machine + add_working_hours(to, number_of_days * max_working_hours_in_a_day) + else + remaining_days = number_of_days + rolling_date = to + loop do + remaining_days -= business_day(rolling_date).number_of_working_hours * 1.0 / max_working_hours_in_a_day + break if remaining_days < 0 + rolling_date = roll_forward rolling_date.next + end + rolling_date + end end - # Snaps the date to the beginning of the next business day, unless it is already within the working hours. + # Snaps the date to the beginning of the next business day, unless it is already within the working hours of a business day. # # @param date [Date, Time] def roll_forward date bday = business_day(date) if bday.include?(date) date elsif bday.starts_after?(date) bday.at_beginning else - roll_forward date.tomorrow.beginning_of_day + roll_forward(date.is_a?(Date) ? date.tomorrow : date.tomorrow.beginning_of_day) end end # Snaps the date to the beginning of the next business day. def at_beginning_of_next_business_day date @@ -109,9 +122,9 @@ dow = date.strftime '%a' BusinessDay.new date, (holiday?(date) ? EmptyWorkingHours.new : @working_hours[dow]) end def max_working_hours_in_a_day - @working_hours.values.map(&:quantity).max + @max_working_hours_in_a_day ||= @working_hours.values.map(&:quantity).max end end end