Here's my effort.  I didn't get around to testing it, but the concept  
seems sound.  I decided to interpret the goal a little more  
conservatively and instead of just making sure the displayed time  
never goes forward, I decided to make sure the offset never goes  
backwards.  To do this, I made the max delta from the current offset  
no more than the amount of time that passed since the last offset  
update:



class FuzzyTime
   MAX_OFFSET = 5*60

   def initialize(*args)
     now = Time.new
     @internal_time = args[0] || now
     @time_offset = now - @internal_time
     @fuzzy_secs = 0
     @last_calc = Time.new
   end

   def actual
     @internal_time
   end

   def update
     @internal_time = Time.new + @time_offset
   end

   def advance(amount)
     @time_offset += amount.to_i
   end

   def calc_offset
     # Choose a new  offset that's between +/- 5 mins.   If it has been
     # less than 5 mins since the last offset calc, choose that time as
     # a max delta (this makes sure time is always going forward)

     time_from_last_calc = (Time.new - @last_calc).to_i

     if time_from_last_calc > 0
       begin
         max_delta = [MAX_OFFSET, time_from_last_calc].min

         delta = rand((2*max_delta) + 1) - max_delta
       end until (delta + @fuzzy_secs).abs < MAX_OFFSET
       @fuzzy_secs += delta

       puts "Fuzzy secs now: #{@fuzzy_secs}"

       @last_calc = Time.new
     end
     @fuzzy_secs
   end

   def get_time
     fuzzy_hour = @internal_time.hour
     fuzzy_min = @internal_time.min
     fuzzy_sec = @internal_time.sec + calc_offset

     if fuzzy_sec > 60
       fuzzy_sec -= 60
       fuzzy_min += 1
     end

     if fuzzy_sec < 0
       fuzzy_sec += 60
       fuzzy_min -= 1
     end


     if fuzzy_min > 60
       fuzzy_min -= 60
       fuzzy_hour = (fuzzy_hour + 1) % 24
     end

     if fuzzy_min < 0
       fuzzy_min += 60
       fuzzy_hour = (fuzzy_hour + 23) % 24
     end

     [fuzzy_hour, fuzzy_min, fuzzy_sec]
   end

   def to_s
     fuzzy_hour, fuzzy_min, fuzzy_sec = get_time
     "#{fuzzy_hour}:#{fuzzy_min / 10}~"
     # "#{fuzzy_hour}:#{fuzzy_min / 10}~ (#{fuzzy_hour}:#{"%02d" %  
fuzzy_min}:#{"%02d" % fuzzy_sec})"
   end

end

if $0 == __FILE__
   t = FuzzyTime.new
   10.times do
     puts t, Time.new
     sleep 10
     t.update
   end
end