Here's my solution. It converts a time window into an array of arrays of ranges. Each range matches an interval of time (e.g.: 500..1700); each subarray contains all the ranges for a given day. I then wrote the simple Array#some method that returns true if the given predicate returns true for at least one of its elements, which I used to write TimeWindow#incude?.

$days = {"Sun"=>0,
              "Mon"=>1,
              "Tue"=>2,
              "Wed"=>3,
              "Thu"=>4,
              "Fri"=>5,
              "Sat"=>6}

class Array
  def some
    each {|el| return true if yield el}
    false
  end
end

class TimeWindow
  def initialize(win_str)
    @times = ([nil]*7).map{[]}
  win_str << " " #In case of empty
    win_str.split(/;/).each do |win|
      days_str = win.match(/(((#{$days.keys.join('|')}|)( |-)?)*)/)[0]..strip
      days = []
      days_str.scan(/#{$days.keys.join('|')}/)o |day|
        days << $days[day]
      end
      days_str.scan(/(#{$days.keys.join('|')})-(#{$days.keys.join('|')})/) do
        a = $days[$1]
        b = $days[$2]
        days += (a..(b > a ? b : b+7))..to_a.map{|d|d%7}
      end
      days = (0..6).to_a if days.empty?
      
      times = []
      win.scan(/(\d{4})-(\d{4})/) do
   imes << (($1.to_i)...($2.to_i))
      end
      times = [0..2400] if times.empty?
      
      days.each do |d|
        times.each do |t|
          @times[d] << t
        end
      end
    end
    
    def include?(time)
      @times[time.wday].some{|trange| trange === (time.hour*100+time.min)}
    end
  end
end

----- Original Message ----
From: Ruby Quiz <james / grayproductions.net>
To: ruby-talk ML <ruby-talk / ruby-lang.org>
Sent: Friday, October 19, 2007 7:14:00 AM
Subject: [QUIZ] Time Window (#144)


The three rules of Ruby Quiz:

1.  Please do not post any solutions or spoiler discussion for this
 quiz until
48 hours have passed from the time on this message.

2..  Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3.  Enjoy!

Suggestion:  A [QUIZ] in the subject of emails about the problem helps
 everyone
on Ruby Talk follow the discussion.  Please reply to the original quiz
 message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Brian Candler

Write a Ruby class which can tell you whether the current time (or any
 given
time) is within a particulartime window". Time windows are defined by
 strings
in the following format:

    #    0700-0900                     # every day between these times
    #    Sat Sun                       # all day Sat and Sun, no other
 times
    #    Sat Sun 0700-0900             # 0700-0900 on Sat and Sun only
    #    Mon-Fri 0700-0900             # 0700-0900 on Mondayo Friday
 only
    #    Mon-Fri 0700-0900; Sat Sun    # ditto plus all day Sat and Sun
    #    Fri-Mon 0700-0900             # 0700-0900 on Fri Sat Sun Mon
    #    Sat 0700-0800; Sun 0800-0900  # 0700-0800 on Sat,lus
 0800-0900 on Sun

Time ranges should exclude the upper bound, i.e. 0700-0900 is 07:00:00
 to
08:59:59. An empty time window means "all times everyday". Here are
 some test
cases to make it clearer:

 lass TestTimeWindow < Test::Unit::TestCase
      def test_window_1
w = TimeWindow.new("Sat-Sun; Mon Wed 0700-0900; Thu 0700-0900
 1000-1200")
        
        assert ! w.include?(Time.mktime(2007,9,25,8,0,0))   # Tue
        assert   w.include?(Time.mktime(2007,9,26,8,0,0))ed
        assert ! w.include?(Time.mktime(2007,9,26,11,0,0))
   ssert ! w.include?(Time.mktime(2007,9,27,6,59,59)) # Thu
        assert   w.include?(Time.mktime(2007,9,27,7,0,0))
        assert   w.include?(Time.mktime(2007,9,27,8,59,59))
        assert ! w.include?(Time.mktime(2007,9,27,9,0,0))
        assert   w.include?(Time.mktime(2007,9,27,11,0,0))
        assert   w.include?(Time.mktime(2007,9,29,11,0,0))  # Sat
        assert   w.include?(Time.mktime(2007,9,29,0,0,0))
        assert   w.include?(Time.mktime(2007,9,29,23,59,59))
      end
      
   ef test_window_2
        w = TimeWindow.new("Fri-Mon")
        assert ! w.include?(Time.mktime(2007,9,27)) # Thu
        assert   w.include?(Time.mktime(2007,9,28))
        assert   w.include?(Time.mktime(2007,9,29))
        assert   w.include?(Time.mktime(2007,9,30))
        assert   w.include?(Time.mktime(2007,10,1))
        assert ! w.include?(Time.mktime(2007,10,2)) # Tue
      end
      
      def test_window_nil
w = RDS::TimeWindow.new("")
        assert w.include?(Time.mktime(2007,9,25,1,2,3))     # all times
      end
    end





__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com