class TimeSlot
cattr_accessor :logger
attr_reader :dow, :days, :months, :pblock
attr_accessor :start, :end
def initialize(slot={})
slot.symbolize_keys!
@start = to_hour_min(slot[:start])
@end = to_hour_min(slot[:end])
@dow = slot[:dow]
@days = slot[:days]
@months = slot[:months]
@pblock = slot[:"programming block"]
raise "invalid time slot: #{self.inspect}" unless valid?
end
def ==(other)
return compare_to_time(other) == 0 if other.kind_of?(Time)
@start == other.start &&
@end == other.end &&
@dow == other.dow &&
@days == other.days &&
@months == other.months
end
def <(other)
s = Time.parse(@start) <=> Time.parse(other.start)
e = Time.parse(@end) <=> Time.parse(other.end)
s == -1 || (s == 0 && e == 1)
end
def >(other)
s = Time.parse(@start) <=> Time.parse(other.start)
e = Time.parse(@end) <=> Time.parse(other.end)
s == 1 || (s == 0 && e == -1)
end
def <=>(other)
return compare_to_time(other) if other.kind_of?(Time)
if self < other
-1
elsif self == other
0
else
1
end
end
def duration(block_size=15.minutes)
s = Time.parse(@start)
e = Time.parse(@end)
if s < e
(e - s).to_i / block_size
else
e += 1.day
(e - s).to_i / block_size
end
end
def self.default
TimeSlot.new(:start => 0, :end => 24)
end
# Take a start or end time, specified as a string, in the format "hh:mm" and
# return an array of integers, [mm, hh]. The original format is that
# produced by to_hour_min, while the output format is useful for blending
# into an array to be passed to a Time.local call.
def self.from_hour_min(hm)
hm.split(":").collect {|x| x.to_i}.reverse
end
# Take a time object, and replace its hours and minutes with the string,
# hm. The string hm should be in the format "hh:mm", much like that
# returned by to_hour_min. Returns a Time object.
def self.blend_with(hm, time)
ar = time.to_a
ar[1,2] = from_hour_min(hm)
Time.local(*ar)
end
def compare_to_time(other)
s = TimeSlot.blend_with(@start, other)
e = TimeSlot.blend_with(@end, other)
if other < s
1
elsif other > e
-1
else
0
end
end
def is_now?(time=Time.now)
s = TimeSlot.blend_with(@start, time)
e = TimeSlot.blend_with(@end, time)
e += 24.hours if @end == "00:00"
if time < s
false
elsif time >= e
false
else
is_today?(time)
end
end
def is_today?(time=Time.now)
if @months && !@months.include?(time.month)
false
elsif @dow && !@dow.include?(time.wday)
false
elsif @days && !@days.include?(time.day)
false
else
true
end
end
def valid?
return false if @start.nil?
return false if @end.nil?
return false if @end <= @start && Time.parse(@end).hour != 0
true
end
def to_hour_min(time_str)
begin
/(\d{1,2})(?::(\d{2}))?/.match(time_str.to_s)
hour = $~[1].to_i % 24
min = $~[2].to_i
sprintf("%02d:%02d", hour, min)
rescue
raise "invalid time slot: #{time_str.inspect}"
end
end
end