From: Gordon Thiesfeld Date: 2007-10-22T05:06:35+09:00 Subject: Re: [QUIZ] Time Window (#144) Here's my solutions. I used Runt for the heavy lifting. I just had to parse the string and create Runt temporal expressions. require 'runt' #adds ability to check Runt expressions against Time objects class Time include Runt::DPrecision attr_accessor :date_precision def date_precision return @date_precision unless @date_precision.nil? return Runt::DPrecision::DEFAULT end end module Runt #extends REWeek to allow for spanning across weeks class REWeek def initialize(start_day,end_day=6) @start_day = start_day @end_day = end_day end def include?(date) return true if @start_day==@end_day if @start_day < @end_day @start_day<=date.wday && @end_day>=date.wday else (@start_day<=date.wday && 6 >=date.wday) || (0 <=date.wday && @end_day >=date.wday) end end end class StringParser < Runt::Intersect def initialize(string) super() add parsed(string) end #recursive method to parse input string def parse(token) case token when "" REWeek.new(0) when /^(.+);(.+)/ # split at semicolons parse($1) | parse($2) when /(\D+) (\d.+)/ # split days and times parse($1) & parse($2) when /(\D+) (\D+)/, /(\d+-\d+) (\d+-\d+)/ # split at spaces parse($1) | parse($2) when /([A-Z][a-z][a-z])-([A-Z][a-z][a-z])/ # create range of days REWeek.new(Runt.const_get($1), Runt.const_get($2)) when /([A-Z][a-z][a-z])/ # create single day DIWeek.new(Runt.const_get($1)) when /(\d\d)(\d\d)-(\d\d)(\d\d)/ #create time range start = Time.mktime(2000,1,1,$1.to_i,$2.to_i) # 0600-0900 should work like 0600-0859, stop = Time.mktime(2000,1,1,$3.to_i,$4.to_i) - 60 REDay.new(start.hour, start.min, stop.hour, stop.min) end end alias :parsed :parse end end class TimeWindow < Runt::StringParser end