From: Sam Roberts Date: 2004-04-01T10:02:11+09:00 Subject: Re: Representing Time Ranges (Difference) Quoteing cc1@cec.wustl.edu, on Thu, Apr 01, 2004 at 07:44:25AM +0900: > Hmm, perhaps I scanned it too quickly, but this feels more like a > library to manipulate date ranges, as opposed to formatting a time span. > Basically I want to be able to represent time spans in a more > meaningful manner then individual seconds. I know all I need to do is > do a bunch of divide / modulus operations to find this out, but I was > wondering if there was a prewritten module to nicely format time spans > and allow easy access to the number of months, days, hours, seconds in > between to time or date objects. Well, I've been meaning to do this, for the same reasons (I have durations in seconds, and I want to print them in more human units). I hacked this up. It works OK, but only up to days. I could extend it to years, but it turns out months is hard to do. Given a span in seconds, you don't know how many months that is, unless you know the date at one end of the span. So, maybe it would be possible to add a Duration.difference(t0, t1), where t0 and t1 are either Time, Date, or DateTime, and then it would be possible to break down the duration into years, months, days, ... But, this hack will do me for now. If you get something better going, pls share it around! Cheers, Sam =begin $Id: duration.rb,v 1.1 2004/04/01 01:00:29 sam Exp $ Copyright (C) 2004 Sam Roberts This library is free software; you can redistribute it and/or modify it under the same terms as the ruby language itself, see the file COPYING for details. =end module Vpim class Duration SECS_HOUR = 60 * 60 SECS_DAY = 24 * SECS_HOUR MINS_HOUR = 60 def initialize(secs) @secs = secs end def Duration.secs(secs) Duration.new(secs) end def Duration.mins(mins) Duration.new(mins * 60) end def Duration.hours(hours) Duration.new(hours * SECS_HOUR) end def Duration.days(days) Duration.new(days * SECS_DAY) end def secs @secs end def mins (@secs/60).to_i end def hours (@secs/SECS_HOUR).to_i end def days (@secs/SECS_DAY).to_i end def weeks (days/7).to_i end def by_hours [ hours, mins % MINS_HOUR, secs % 60] end def by_days [ days, hours % 24, mins % MINS_HOUR, secs % 60] end def to_a by_days end def to_s Duration.as_str(self.to_a) end def Duration.as_str(arr) s = "" case arr.length when 4 if arr[0] > 0 s << "#{arr[0]} days" end if arr[1] > 0 if s.length > 0 s << ', ' end s << "#{arr[1]} hours" end if arr[2] > 0 if s.length > 0 s << ', ' end s << "#{arr[2]} mins" end if arr[3] > 0 if s.length > 0 s << ', ' end s << "#{arr[3]} secs" end when 3 if arr[0] > 0 s << "#{arr[0]} hours" end if arr[1] > 0 if s.length > 0 s << ', ' end s << "#{arr[1]} mins" end if arr[2] > 0 if s.length > 0 s << ', ' end s << "#{arr[2]} secs" end end s end end end