how to add one month or one week to a given Time?

S

Sven Bauhan

Hi,

I want to add a given time difference to an Time object. My first idea was
to calculate the number of seconds of this time difference. This works for
values like hours or days, but when I want to add a month, the number of
seconds depends on the number of days in the given month.
My second idea was to use a vector to add the time:

@@sec = Vector[ 0, 0, 0, 0, 0, 1 ]
@@min = Vector[ 0, 0, 0, 0, 1, 0 ]
@@hour = Vector[ 0, 0, 0, 1, 0, 0 ]
@@day = Vector[ 0, 0, 1, 0, 0, 0 ]
@@week = Vector[ 0, 0, 7, 0, 0, 0 ]
@@month = Vector[ 0, 1, 0, 0, 0, 0 ]
@@year = Vector[ 1, 0, 0, 0, 0, 0 ]

def next! ( distance = @@year )
return @next if ( 0 == distance )
now = Time.now()
values = Vector[ @next.year, @next.mon, @next.day,
@next.hour, @next.min, @next.sec ]
while ( @next.to_i() < now.to_i() )
values += distance
@next = Time.local( *values.to_a )
end
return @next
end

But this can result in an "argument out of range" error.

Has someone a simple solution for this problem?

Thanks,
Sven
 
S

Sam Roberts

Quoteing (e-mail address removed), on Mon, Jan 31, 2005 at 06:10:47AM +0900:
Hi,

I want to add a given time difference to an Time object. My first idea was
to calculate the number of seconds of this time difference. This works for
values like hours or days, but when I want to add a month, the number of
seconds depends on the number of days in the given month.

Yep, not as simple as you might hope.

I extend Time in my vPim package to do this. Here's the code, note that
it uses Date (since Date knows about oddities of leap minutes, days in
a month, leap years, etc.). Note the rounding effects.

If you are doing more stuff with dates and times, you might find other
useful code in vPim.

Cheers,
Sam



=begin
$Id: time.rb,v 1.4 2004/11/17 05:06:27 sam Exp $

Copyright (C) 2005 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

require 'date'

# Extensions to builtin Time allowing addition to Time by multiples of other
# intervals than a second.

class Time
# Returns a new Time, +years+ later than this time. Feb 29 of a
# leap year will be rounded up to Mar 1 if the target date is not a leap
# year.
def plus_year(years)
Time.local(year + years, month, day, hour, min, sec, usec)
end

# Returns a new Time, +months+ later than this time. The day will be
# rounded down if it is not valid for that month.
# 31 plus 1 month will be on Feb 28!
def plus_month(months)
d = Date.new(year, month, day)
d >>= months
Time.local(d.year, d.month, d.day, hour, min, sec, usec)
end

# Returns a new Time, +days+ later than this time.
# Does this do as I expect over DST? What if the hour doesn't exist
# in the next day, due to DST changes?
def plus_day(days)
d = Date.new(year, month, day)
d += days
Time.local(d.year, d.month, d.day, hour, min, sec, usec)
end
end
 
R

Robert Klemme

Sven Bauhan said:
Hi,

I want to add a given time difference to an Time object. My first idea was
to calculate the number of seconds of this time difference. This works for
values like hours or days, but when I want to add a month, the number of
seconds depends on the number of days in the given month.
My second idea was to use a vector to add the time:

@@sec = Vector[ 0, 0, 0, 0, 0, 1 ]
@@min = Vector[ 0, 0, 0, 0, 1, 0 ]
@@hour = Vector[ 0, 0, 0, 1, 0, 0 ]
@@day = Vector[ 0, 0, 1, 0, 0, 0 ]
@@week = Vector[ 0, 0, 7, 0, 0, 0 ]
@@month = Vector[ 0, 1, 0, 0, 0, 0 ]
@@year = Vector[ 1, 0, 0, 0, 0, 0 ]

def next! ( distance = @@year )
return @next if ( 0 == distance )
now = Time.now()
values = Vector[ @next.year, @next.mon, @next.day,
@next.hour, @next.min, @next.sec ]
while ( @next.to_i() < now.to_i() )
values += distance
@next = Time.local( *values.to_a )
end
return @next
end

But this can result in an "argument out of range" error.

Has someone a simple solution for this problem?

You can use the array representation of Time for some of the manipulations:
t = Time.now => Sun Jan 30 23:47:24 GMT+1:00 2005
a = t.to_a => [24, 47, 23, 30, 1, 2005, 0, 30, false, "GMT+1:00"]
a[4] += 1 => 2
a => [24, 47, 23, 30, 2, 2005, 0, 30, false, "GMT+1:00"]
t2 = Time.local *a
=> Wed Mar 02 23:47:24 GMT+1:00 2005

Regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top