From: Philip Gatt Date: 2007-10-22T14:33:47+09:00 Subject: Re: [QUIZ] Time Window (#144) Here is my solution to the time window quiz. Range.create_from_string is the workhorse method and it would be nice if that was refactored into smaller pieces. class TimeWindow def initialize(definition_string) @ranges = [] definition_string.split(/;/).each do |part| @ranges << Range.create_from_string(part.strip) end @ranges << Range.create_from_string('') if @ranges.empty? end def include?(time) @ranges.any? {|r| r.include?(time)} end class Range < Struct.new(:day_parts, :time_parts) DAYS = %w{Sun Mon Tue Wed Thu Fri Sat} def self.create_from_string(str) time_parts = [] day_parts = [] str.split(/ /).each do |token| token.strip! if DAYS.include?(token) day_parts << token elsif token =~ /^(\w{3})-(\w{3})$/ start_day, end_day = $1, $2 start_found = false (DAYS * 2).each do |d| start_found = true if d == start_day day_parts << d if start_found break if d == end_day && start_found end elsif token =~ /^(\d{4})-(\d{4})$/ time_parts << (($1.to_i)..($2.to_i - 1)) else raise "Unrecognized token: #{token}" end end time_parts << (0..2399) if time_parts.empty? day_parts = DAYS.clone if day_parts.empty? self.new(day_parts, time_parts) end def include?(time) matches_day?(time) && matches_minute?(time) end def matches_day?(time) day = time.strftime('%a') self.day_parts.include?(day) end def matches_minute?(time) minute = time.strftime('%H%M').to_i self.time_parts.any? {|tp| tp.include?(minute) } end end end