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