Here's my solution. It converts a time window into an array of arrays of ra=
nges. Each range matches an interval of time (e.g.: 500..1700); each subarr=
ay contains all the ranges for a given day. I then wrote the simple Array#s=
ome method that returns true if the given predicate returns true for at lea=
st one of its elements, which I used to write TimeWindow#incude?.=0A=0A$day=
s =3D {"Sun"=3D>0,=0A              "Mon"=3D>1,=0A              "Tue"=3D>2,=
=0A              "Wed"=3D>3,=0A              "Thu"=3D>4,=0A              "F=
ri"=3D>5,=0A              "Sat"=3D>6}=0A=0Aclass Array=0A  def some=0A    e=
ach {|el| return true if yield el}=0A    false=0A  end=0Aend=0A=0Aclass Tim=
eWindow=0A  def initialize(win_str)=0A    @times =3D ([nil]*7).map{[]}=0A  =
  win_str << " " #In case of empty=0A    win_str.split(/;/).each do |win|=
=0A      days_str =3D win.match(/(((#{$days.keys.join('|')}|)( |-)?)*)/)[0]=
..strip=0A      days =3D []=0A      days_str.scan(/#{$days.keys.join('|')}/)=
 do |day|=0A        days << $days[day]=0A      end=0A      days_str.scan(/(=
#{$days.keys.join('|')})-(#{$days.keys.join('|')})/) do=0A        a =3D $da=
ys[$1]=0A        b =3D $days[$2]=0A        days +=3D (a..(b > a ? b : b+7))=
..to_a.map{|d|d%7}=0A      end=0A      days =3D (0..6).to_a if days.empty?=
=0A      =0A      times =3D []=0A      win.scan(/(\d{4})-(\d{4})/) do=0A   =
     times << (($1.to_i)...($2.to_i))=0A      end=0A      times =3D [0..240=
0] if times.empty?=0A      =0A      days.each do |d|=0A        times.each d=
o |t|=0A          @times[d] << t=0A        end=0A      end=0A    end=0A    =
=0A    def include?(time)=0A      @times[time.wday].some{|trange| trange =
=3D=3D=3D (time.hour*100+time.min)}=0A    end=0A  end=0Aend=0A=0A----- Orig=
inal Message ----=0AFrom: Ruby Quiz <james / grayproductions.net>=0ATo: ruby-=
talk ML <ruby-talk / ruby-lang.org>=0ASent: Friday, October 19, 2007 7:14:00 =
AM=0ASubject: [QUIZ] Time Window (#144)=0A=0A=0AThe three rules of Ruby Qui=
z:=0A=0A1.  Please do not post any solutions or spoiler discussion for this=
=0A quiz until=0A48 hours have passed from the time on this message.=0A=0A2=
..  Support Ruby Quiz by submitting ideas as often as you can:=0A=0Ahttp://w=
ww.rubyquiz.com/=0A=0A3.  Enjoy!=0A=0ASuggestion:  A [QUIZ] in the subject =
of emails about the problem helps=0A everyone=0Aon Ruby Talk follow the dis=
cussion.  Please reply to the original quiz=0A message,=0Aif you can.=0A=0A=
-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D=
-=3D-=3D-=3D=0A=0Aby Brian Candler=0A=0AWrite a Ruby class which can tell y=
ou whether the current time (or any=0A given=0Atime) is within a particular=
 "time window". Time windows are defined by=0A strings=0Ain the following f=
ormat:=0A=0A    #    0700-0900                     # every day between thes=
e times=0A    #    Sat Sun                       # all day Sat and Sun, no =
other=0A times=0A    #    Sat Sun 0700-0900             # 0700-0900 on Sat =
and Sun only=0A    #    Mon-Fri 0700-0900             # 0700-0900 on Monday=
 to Friday=0A only=0A    #    Mon-Fri 0700-0900; Sat Sun    # ditto plus al=
l day Sat and Sun=0A    #    Fri-Mon 0700-0900             # 0700-0900 on F=
ri Sat Sun Mon=0A    #    Sat 0700-0800; Sun 0800-0900  # 0700-0800 on Sat,=
 plus=0A 0800-0900 on Sun=0A=0ATime ranges should exclude the upper bound, =
i.e. 0700-0900 is 07:00:00=0A to=0A08:59:59. An empty time window means "al=
l times everyday". Here are=0A some test=0Acases to make it clearer:=0A=0A =
   class TestTimeWindow < Test::Unit::TestCase=0A      def test_window_1=0A=
        w =3D TimeWindow.new("Sat-Sun; Mon Wed 0700-0900; Thu 0700-0900=0A =
1000-1200")=0A        =0A        assert ! w.include?(Time.mktime(2007,9,25,=
8,0,0))   # Tue=0A        assert   w.include?(Time.mktime(2007,9,26,8,0,0))=
   # Wed=0A        assert ! w.include?(Time.mktime(2007,9,26,11,0,0))=0A   =
     assert ! w.include?(Time.mktime(2007,9,27,6,59,59)) # Thu=0A        as=
sert   w.include?(Time.mktime(2007,9,27,7,0,0))=0A        assert   w.includ=
e?(Time.mktime(2007,9,27,8,59,59))=0A        assert ! w.include?(Time.mktim=
e(2007,9,27,9,0,0))=0A        assert   w.include?(Time.mktime(2007,9,27,11,=
0,0))=0A        assert   w.include?(Time.mktime(2007,9,29,11,0,0))  # Sat=
=0A        assert   w.include?(Time.mktime(2007,9,29,0,0,0))=0A        asse=
rt   w.include?(Time.mktime(2007,9,29,23,59,59))=0A      end=0A      =0A   =
   def test_window_2=0A        w =3D TimeWindow.new("Fri-Mon")=0A        as=
sert ! w.include?(Time.mktime(2007,9,27)) # Thu=0A        assert   w.includ=
e?(Time.mktime(2007,9,28))=0A        assert   w.include?(Time.mktime(2007,9=
,29))=0A        assert   w.include?(Time.mktime(2007,9,30))=0A        asser=
t   w.include?(Time.mktime(2007,10,1))=0A        assert ! w.include?(Time.m=
ktime(2007,10,2)) # Tue=0A      end=0A      =0A      def test_window_nil=0A=
        w =3D RDS::TimeWindow.new("")=0A        assert w.include?(Time.mkti=
me(2007,9,25,1,2,3))     # all times=0A      end=0A    end=0A=0A=0A=0A=0A=
=0A__________________________________________________=0ADo You Yahoo!?=0ATi=
red of spam?  Yahoo! Mail has the best spam protection around =0Ahttp://mai=
l.yahoo.com