On Thu, Sep 13, 2012 at 1:54 PM, Matthew Kerwin <matthew / kerwin.net.au> wrote:
> Sorry if my answer was a bit air-headed.  Here's a more tangible example:
>
>     class HoursMinutes
>       attr_accessor :hours
>       attr_reader :minutes
>       def initialize h,m
>         @hours = h
>         self.minutes = m
>       end
>       def <=> o
>         r = (@hours <=> o.hours)
>         r = (@minutes <=> o.minutes) if r == 0
>         r
>       end
>       def succ
>         HoursMinutes.new(@hours, @minutes+1)
>       end
>       def minutes= m
>         while m > 60
>           @hours += 1
>           m -= 60
>         end
>         while m < 0
>           @hours -= 1
>           m += 60
>         end
>         @minutes = m
>       end
>       def to_s
>         "%d:%02d" % [@hours, @minutes]
>       end
>     end
>
>     range = HoursMinutes.new(8,0)..HoursMinutes.new(9,0)
>     p range.to_a
>
> The spaceship operator will break if `o` doesn't quack like an
> HoursMinutes object, and it's not very useful, but it might be a
> decent starting place.

Your #succ method does not overflow.  I would make the class immutable
since that has some advantages.  Here's a different solution which
also includes range checking and basic math.

class HoursMinute
  attr_reader :hour, :minute

  def initialize(hr, mn)
    raise ArgumentError, "Out of range: %2d:%02d" % [hr, mn] unless
      (0..23).include?(hr) && (0..59).include?(mn)
    @hour = hr.to_int
    @minute = mn.to_int
  end

  def to_s; "%2d:%02d" % [hour, minute] end

  def succ; self + 1 end

  def +(min)
    hr, mn = (hour * 60 + minute + min.to_int).divmod 60
    self.class.new(hr % 24, mn)
  end

  def -(min) self + -min end

  def hash; hour * 60 + minute end
  def eql?(o) hour == o.hour && minute == o.minute end

  def <=>(o) (hour <=> o.hour).nonzero? || minute <=> o.minute end
 end


Kind regards

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/