Reputation: 11653
The code below helps calculate business hours for completing tasks. In the calculate_deadline
method, in the BusinesHours Class, the two puts statements reveal this
puts self
#<BusinessHours:0x000001008cbb70>
puts self[start_time.to_date].inspect
#<TimeRange:0x000001008cbb48 @range=2010-06-10 09:00:00 -0700..2010-06-10 15:00:00 -0700>
I don't understand why putting start_time.to_date beside 'self' in calculate_deadline changes self from BusinessHours class to TimeRange class, as the two puts statements suggest, especially since the 'to_date' method is part of class Time. Can you explain how this is happening?
require 'time'
require 'date'
class Time
def to_date
Date.new(year, month, day)
end
end
class BusinessHours
def initialize(time_in, time_out)
@default_range = TimeRange.new(time_in, time_out)
@modified_days = {}
end
def update(day, time_in, time_out)
key = day.is_a?(Symbol) ? day : Date.parse(day)
@modified_days.merge!({key => TimeRange.new(time_in, time_out)})
end
def closed(*days)
days.each {|day| update(day, '0:00', '0:00')}
end
def [](date)
day_of_week = date.strftime("%a").downcase.to_sym
range = @modified_days[date] || @modified_days[day_of_week] || @default_range
# reset time range dates to match date param
range.reset_date(date)
range
end
def calculate_deadline(seconds, start_time)
start_time = Time.parse(start_time)
puts self
puts self[start_time.to_date].inspect
range = self[start_time.to_date]
if range.applies?(start_time)
start_time = [start_time, range.start].max
available_seconds = range.stop - start_time
return start_time + seconds if available_seconds > seconds
seconds -= available_seconds
end
calculate_deadline(seconds, (start_time.to_date + 1).to_s)
end
end
class TimeRange
def initialize(time_in, time_out)
@range = Time.parse(time_in)..Time.parse(time_out)
end
def reset_date(date)
@range = Time.local(date.year, date.month, date.day, start.hour, start.min)..
Time.local(date.year, date.month, date.day, stop.hour, stop.min)
end
def applies?(time)
stop > time
end
def stop
@range.end
end
def start
@range.begin
end
end
k = BusinessHours.new("9:00 AM", "3:00 PM")
k.calculate_deadline(20*60*60, "Jun 7, 2010 10:45 AM")
Upvotes: 1
Views: 94
Reputation: 8941
@default_range = TimeRange.new(time_in, time_out)
From that line, we can see that @default_range
is a TimeRange
instance, and that @modified_days
is an empty hash (therefore @modified_days[anything]
will be nil, i.e. falsey).
range = @modified_days[date] || @modified_days[day_of_week] || @default_range
Since @modified_days[anything]
is falsey, range
ends up being @default_range
, which, as we see above, is a TimeRange
object. Your []
method on BusinessHours
returns the range
variable, which is a TimeRange
object.
Therefore, with self
being a BusinessHours
object, when you call the []
method (self[argument]
), you will get a TimeRange
object.
Upvotes: 2
Reputation: 15010
It does not change your self
. You are inspecting a different object.
self.inspect # inspecting 'self'.
self[date].inspect # inspecting 'self[date]'
# which returns a `TimeRange` object `range`.
# Hence, you are inspecting `range`.
Upvotes: 0