From: Robert Klemme Date: 2012-09-13T22:43:04+09:00 Subject: Re: ruby Range to array that acts like time objects? On Thu, Sep 13, 2012 at 1:54 PM, Matthew Kerwin 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/