Hi,

my solution is definitely over-engineered :-)

There are three classes:
WeekDay: a day of the week
DayRange: a range between two days of the week
DayRangeArray: a list of DayRanges.

The DayRangeArray constructor does the work of splitting a list
of days into DayRange instances.

Regards,
Boris

### day_range.rb
require 'date'

# A day of the week. In calculations and comparisons a WeekDay behaves
# like an integer with 1=Monday, ..., 7=Sunday.
class WeekDay
   # A WeekDay can be constructed from a number between 1 and 7 or a
   # string like 'mon' or 'monday'.
   def initialize(arg)
     case arg
     when Fixnum
       if arg < 1 or arg > 7
         raise ArgumentError.new("day number must be between 1 and 7")
       end
       @daynum = arg
     when WeekDay
       @daynum = arg.to_i
     else
       s = arg.to_s.downcase
       if Date::ABBR_DAYS.has_key?(s)
         @daynum = Date::ABBR_DAYS[s]
       elsif Date::DAYS.has_key?(s)
         @daynum = Date::DAYS[s]
       else
         raise ArgumentError.new("#{s} is not a day")
       end
       @daynum = 7 if @daynum == 0
     end
   end

   # Returns the abbreviated name of the day (e.g. 'Mon')
   def to_s
     Date::ABBR_DAYNAMES[@daynum % 7]
   end

   # Returns the number of the day (1=Monday, ..., 7=Sunday)
   def to_i
     @daynum
   end

   %w{== <=> + - >}.each do |meth|
     define_method meth do |other|
       self.to_i.send(meth, other.to_i)
     end
   end
end

# A Range of days between two days of the week.
class DayRange < Range
   # The first and last day of the range can be given as instances of
   # class WeekDay, numbers or strings.
   def initialize(from, to, exclusive=false)
     from_day = WeekDay.new(from)
     to_day   = WeekDay.new(to)
     super(from_day, to_day, exclusive)
   end

   # Returns a string representation of the range. Two consecutive days
   # are returned as a list, e.g. 'Mon, Tue'.
   def to_s
     from = self.begin.to_s
     to   = self.end.to_s

     case self.end - self.begin
     when 0 then return from
     when 1 then return from + ', ' + to
     else        return from + '-'  + to
     end
   end
end

# An array containing several DayRange instances.
class DayRangeArray < Array
   private
   def normalize_days days
     days.collect{|d| WeekDay.new(d)}.sort.uniq
   end

   # Given a list of days (as numbers or strings), an array of
   # DayRanges is created.
   def initialize(*days)
     return if days.size == 0

     a = normalize_days(days)
     first = a.first

     1.upto(a.size - 1) do |i|
       if a[i] > a[i-1] + 1
         self << DayRange.new(first, a[i-1])
         first = a[i]
       end
     end
     self << DayRange.new(first, a.last)
   end

   public
   # The DayRanges are separated by comma. For example:
   #   DayRangeArray.new(1, 2, 3, 5).to_s    # => "Mon-Wed, Fri"
   def to_s
     self.join(', ')
   end
end



### day_range_test.rb
require 'day_range'
require 'test/unit'

class DayRangeTest < Test::Unit::TestCase
   def test_new
     dr = DayRange.new(1, 5)
     assert_equal WeekDay.new(1), dr.begin
     assert_equal WeekDay.new(5), dr.end
   end

   def test_argument_error
     assert_raise(ArgumentError) { DayRange.new(1, 8) }
     assert_raise(ArgumentError) { DayRange.new(0, 3) }
     assert_raise(ArgumentError) { DayRange.new(-1, 3) }

     assert_raise(ArgumentError) { DayRangeArray.new(1, 8) }
     assert_raise(ArgumentError) { DayRangeArray.new('funday') }
   end

   def test_to_s
     assert_equal 'Fri-Sun',  DayRange.new(5, 7).to_s
     assert_equal 'Mon-Fri',  DayRange.new(1, 5).to_s
     assert_equal 'Wed',      DayRange.new(3, 3).to_s
     assert_equal 'Mon, Tue', DayRange.new(1, 2).to_s
   end

   def test_day_range_list
     exp = {
       [1,2,3,4,5,6,7] => 'Mon-Sun',
       [1,2,3,6,7]     => 'Mon-Wed, Sat, Sun',
       [1,3,4,5,6]     => 'Mon, Wed-Sat',
       [2,3,4,6,7]     => 'Tue-Thu, Sat, Sun',
       [1,3,4,6,7]     => 'Mon, Wed, Thu, Sat, Sun',
       [7]             => 'Sun',
       [1,7]           => 'Mon, Sun',
       [7,6,7,4,3]     => 'Wed, Thu, Sat, Sun',
       []              => '',
       ['mon', 'Tuesday', 'WED', 5, 'saturday', 'sUnDaY'] => 'Mon- 
Wed, Fri-Sun'
     }

     exp.each do |list, string|
       assert_equal string,  DayRangeArray.new(*list).to_s
     end
   end
end