Here's my solution with unit tests (I'm trying to get into the habit).  

I made Day a subclass of Date, but I ended up overriding most of the methods I needed, so I don't know if it bought me much.  It also handles wrapping, but can be disabled by commenting out the Day#succ method.

Thanks,

Gordon

#
# day_range.rb
#

class Array
  
  def collapse_ranges(options = {})
        range = []
        return_array = []
        self.each_with_index do |item, i|
            range.push(item)
           # if this is the last item
            # - or -
            # there is another item after this one
            if item == self.last || self[i + 1]
                # if this is the last item
                # - or -
                # the next item is not the item after the current one
                 if item == self.last|| item.succ != self[i + 1]
                    # if there is a range of 3 items or more
                    if range.length >= 3
                        return_array.push(range.first..range.last)
                    # else empty the range individually
                    else
                        return_array.concat range
                    end
                    # clear out the range
                    range.clear
                end
            end
        end

        return return_array
    end
  
  def to_s
    self.map { |i| i.to_s }.join(', ')
  end
end

class Range
  def to_s
    "#{first}-#{last}"
  end
end

require 'date'

class Day < Date

  Days = [nil, "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
  Abbr = [nil, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
  
  def self.commercial(int)
   day = send("from_#{int.class}".downcase.intern, int)
   super(1984,1,day)
  end
 
  def succ
    if cwday == 7
      Day.commercial(1)
    else
      super
    end
  end
  
  def to_s
    Days[cwday]
  end
  
  def to_abbr
    Abbr[cwday]
  end
  
  alias_method :to_s, :to_abbr
  
  def self.from_string(string)
    # If string isn't in Days or Abbr, return string and let Date#commercial raise ArgumentError
    Days.index(string.capitalize) || Abbr.index(string.capitalize) || string.capitalize
  end
  
  def self.from_fixnum(int)
    # Date#commercial allows integers over 7, so raise ArgumentErrror here
    if (1..7).include? int 
      int 
    else
      raise ArgumentError
    end
  end
  
end

class DayRange
  
  def initialize(array)
    @array = array.map{|i| Day.commercial(i) }.collapse_ranges
  end
  
  def to_s
    @array.to_s
  end

end

#
# test_day_range.rb
#

require 'test/unit'
require 'lib/days.rb'

class TestArray < Test::Unit::TestCase
  def test_collapse_ranges
    assert_equal( [(1..4),6], [1,2,3,4,6].collapse_ranges)
  end
  
  def test_to_s
    assert_equal([1,2,3].to_s, '1, 2, 3')
  end
end

class TestRange < Test::Unit::TestCase
  def test_to_s
    assert_equal((1..3).to_s, '1-3')
  end
end

class TestDay < Test::Unit::TestCase
  def setup
    @day = Day.commercial(6)
    @next_day = Day.commercial('Sun')
  end
  
  def test_error
    assert_raise(ArgumentError){ Day.commercial('not') }
    assert_raise(ArgumentError){ Day.commercial(8) }
  end

  def test_succ
    assert_equal(@day.succ.cwday,7)
  end
  
  def test_spaceship
    assert(@day < @next_day)
  end
  
  def test_to_s
    assert_equal('Sat', @day.to_s)
  end
end

class TestDayRange< Test::Unit::TestCase
  def test_to_s 
     [
      [[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"] ,
      [['Tue','Wed','Thu','Fri'],"Tue-Fri"],
      [['Wednesday','Thursday','Friday','Saturday'],"Wed-Sat"],
      [['tue','fri','sat','sun'], "Tue, Fri-Sun"],
      [[5,6,7,1],"Fri-Mon"],
      [[1,5,6,7],"Mon, Fri-Sun"]
    ].each do |arr, str|
      assert_equal(str, DayRange.new(arr).to_s)
    end
      assert_raise(ArgumentError){ DayRange.new([1,8]).to_s }
  end
end