How to add months to a date (datetime object)?

T

tinnews

I have a date in the form of a datetime object and I want to add (for
example) three months to it. At the moment I can't see any very
obvious way of doing this. I need something like:-

myDate = datetime.date.today()
inc = datetime.timedelta(months=3)
myDate += inc

but, of course, timedelta doesn't know about months. I had a look at
the calendar object but that didn't seem to help much.
 
R

Roy Smith

I have a date in the form of a datetime object and I want to add (for
example) three months to it. At the moment I can't see any very
obvious way of doing this. I need something like:-

myDate = datetime.date.today()
inc = datetime.timedelta(months=3)
myDate += inc

but, of course, timedelta doesn't know about months. I had a look at
the calendar object but that didn't seem to help much.

Well, before you can "add three months" to something, you need to explain
what that means.

What is Nov 29th plus 3 months?

What is Jan 31st plus 3 months?

Months are different lengths. Asking to "add 3 months" is kind of like
asking, "If I'm somewhere in the continental US (east of the Mississippi
River) and move three states to the west, how many miles have I moved?"
 
C

Chris Rebert

I have a date in the form of a datetime object and I want to add (for
example) three months to it.  At the moment I can't see any very
obvious way of doing this.  I need something like:-

   myDate = datetime.date.today()
   inc = datetime.timedelta(months=3)
   myDate += inc

but, of course, timedelta doesn't know about months.

Which makes some sense considering a month can range from 28-31 days,
which would make the delta oddly fuzzy.

Here's one approach:
myDate = datetime.date.today()
newYear = myDate.year
newMonth = myDate.month + 3
if newMonth > 12:
newYear += 1
newMonth -= 12
inThreeMonths = datetime.date(newYear, newMonth, myDate.day)
#add extra analogous logic if you have to deal with February or 31st days.

Cheers,
Chris
 
V

Vlastimil Brom

2009/3/15 said:
I have a date in the form of a datetime object and I want to add (for
example) three months to it.  At the moment I can't see any very
obvious way of doing this.  I need something like:-

   myDate = datetime.date.today()
   inc = datetime.timedelta(months=3)
   myDate += inc

but, of course, timedelta doesn't know about months. I had a look at
the calendar object but that didn't seem to help much.

I guess, one can simply do this manually:
datetime.date(2009, 6, 15)


however, one have to check for non existing dates:Traceback (most recent call last):

hth
vbr
 
T

tinnews

Roy Smith said:
Well, before you can "add three months" to something, you need to explain
what that means.

What is Nov 29th plus 3 months?

What is Jan 31st plus 3 months?

Months are different lengths. Asking to "add 3 months" is kind of like
asking, "If I'm somewhere in the continental US (east of the Mississippi
River) and move three states to the west, how many miles have I moved?"

No, it's perfectly possible applying simple logic. My reminder
program manages it perfectly well. I have, for example, two sets of
three monthly reminders.

One starts on Jan 19th and repeats three monthly, that means Jan
19th, April 19th, July 19th and October 19th. Very simple.

The other is a little more difficult, it starts on December 31st
and repeats three monthly. So that one is on December 31st, March
31st, June 30th and September 30th.

The calendar program manages it perfectly well using what seems to me
fairly obvious logic, what I want is to be able to do the same in
Python.

I.e. in simple terms I want the "same day N months hence" and, if it
doesn't exist then the nearest possible.
 
T

tinnews

Chris Rebert said:
Which makes some sense considering a month can range from 28-31 days,
which would make the delta oddly fuzzy.

Here's one approach:
myDate = datetime.date.today()
newYear = myDate.year
newMonth = myDate.month + 3
if newMonth > 12:
newYear += 1
newMonth -= 12
inThreeMonths = datetime.date(newYear, newMonth, myDate.day)
#add extra analogous logic if you have to deal with February or 31st days.
I was just hoping there was some calendar object in Python which could
do all that for me (I need the handling of 31st and February etc.)
 
C

Chris Rebert

No, it's perfectly possible applying simple logic.  My reminder
program manages it perfectly well.  I have, for example, two sets of
three monthly reminders.

   One starts on Jan 19th and repeats three monthly, that means Jan
   19th, April 19th, July 19th and October 19th.  Very simple.

   The other is a little more difficult, it starts on December 31st
   and repeats three monthly.  So that one is on December 31st, March
   31st, June 30th and September 30th.

The calendar program manages it perfectly well using what seems to me
fairly obvious logic, what I want is to be able to do the same in
Python.

I.e. in simple terms I want the "same day N months hence" and, if it
doesn't exist then the nearest possible.

But that's not what you said originally; you now fleshed out important
details. Your original question was simpler and more ambiguous.
The problem here is that there are multiple ways to handle the
ambiguous situations and there's no objective, obvious right choice.
Thus, though one must implement it by oneself, one gets exactly the
behavior one desires.
Besides your behavior, one could equally well argue that a 31st repeat
on months without a 31st should just be dropped, or that it should
carry over onto the 1st of the next month (ignoring the complications
of February). Which behavior one needs is completely
context-dependent.

Cheers,
Chris
 
C

Casey Webster

No, it's perfectly possible applying simple logic.  My reminder
program manages it perfectly well.  I have, for example, two sets of
three monthly reminders.

    One starts on Jan 19th and repeats three monthly, that means Jan
    19th, April 19th, July 19th and October 19th.  Very simple.

    The other is a little more difficult, it starts on December 31st
    and repeats three monthly.  So that one is on December 31st, March
    31st, June 30th and September 30th.

The calendar program manages it perfectly well using what seems to me
fairly obvious logic, what I want is to be able to do the same in
Python.

The example you give does have fairly obvious logic. But how does it
handle Feb 28th, 2009 + 3 months? To me, there are two "obvious"
answers: May 28th, 2009 or May 31st, 2009. The question is intent; is
Feb 28th an arbitrary day of the month, or is it the last day of the
month, which for something like a monthly bill reminder is more likely?
 
J

John Yeung

The example you give does have fairly obvious logic. But how does it
handle Feb 28th, 2009 + 3 months?  To me, there are two "obvious"
answers: May 28th, 2009 or May 31st, 2009.  The question is intent; is
Feb 28th an arbitrary day of the month, or is it the last day of the
month, which for something like a monthly bill reminder is more likely?

In my experience, unless there is explicit verbiage that says "last
day of the month", the day of the month is always retained except
where it would result in an invalid date. (So May 28 in your
example.)

I sympathize with anyone who considers "lay person date math" ugly and
not always logical, in a mathematician's sense of logic. But the fact
of the matter is that LPDM is quite well established and not very
ambiguous at all.

John
 
R

Roy Smith

Well, before you can "add three months" to something, you need to explain
what that means.
[...]
No, it's perfectly possible applying simple logic.

I didn't say it was not possible. I just said that a precursor to doing it
is understand what you mean by "add three months". There is no universal
definition for what that means.
 
R

Roy Smith

Chris Rebert said:
Besides your behavior, one could equally well argue that a 31st repeat
on months without a 31st should just be dropped, or that it should
carry over onto the 1st of the next month (ignoring the complications
of February). Which behavior one needs is completely
context-dependent.

Indeed. For example, my wife started her current job on a Feb 29th. There
are significant financial events that happen on various anniversaries of
her employment (vesting of stock and retirement benefits). It really is
important that everybody know exactly what is meant by "10 years from Feb
29th, on a given year", and what it means in one context may not mean what
it means in another.
 
R

Roy Smith

Chris Rebert said:
Which makes some sense considering a month can range from 28-31 days,
which would make the delta oddly fuzzy.

BTW, what date is "One month after August 10, 1752"? Extra points if you
refuse the answer the question on the grounds that it's incompletely
specified :)
 
C

Chris Rebert

BTW, what date is "One month after August 10, 1752"?  Extra points if you
refuse the answer the question on the grounds that it's incompletely
specified :)

Not that that date could even be represented by most programs since
it's before 1970. Talk about recentism! :)
I've always wondered how historians using computers deal with that limitation...

Cheers,
Chris
 
R

Roy Smith

Chris Rebert said:
Not that that date could even be represented by most programs since
it's before 1970. Talk about recentism! :)
I've always wondered how historians using computers deal with that
limitation...

The unix time format it well known for being extremely limited both in
terms of extent and precision. Julian Date
(http://en.wikipedia.org/wiki/Julian_date) is a commonly used time scale
for working with events far into the past or future.
 
C

CM

I have a date in the form of a datetime object and I want to add (for
example) three months to it.  At the moment I can't see any very
obvious way of doing this.  I need something like:-

    myDate = datetime.date.today()
    inc = datetime.timedelta(months=3)
    myDate += inc

but, of course, timedelta doesn't know about months. I had a look at
the calendar object but that didn't seem to help much.

As someone pointed out, dateutil to the rescue:
datetime.date(2009, 3, 15)
datetime.date(2009, 6, 15)

Che
 
J

John Machin

BTW, what date is "One month after August 10, 1752"?  Extra points if you
refuse the answer the question on the grounds that it's incompletely
specified :)

Yup, which calendar, what religion do you follow, where are you (and
if the answer is Sweden, which parish (according to legend)).
 
J

John Machin

In my experience, unless there is explicit verbiage that says "last
day of the month", the day of the month is always retained except
where it would result in an invalid date.  (So May 28 in your
example.)

I sympathize with anyone who considers "lay person date math" ugly and
not always logical, in a mathematician's sense of logic.  But the fact
of the matter is that LPDM is quite well established and not very
ambiguous at all.

A couple of issues here:

(1) The number of days in a month is not a constant, so "a
mathematician's sense of logic" is quite irrelevant.

(2) The various *different* LPDMs are quite well established and each
of them can be reduced to non-ambiguous rules provided that the
reducer is patient and persistent and avoids terms like "ugly",
"illogical", "ludicrous" ... early stages of the reduction process can
produce things like "31 January plus 1 month -> 3 March (2 March in a
leap year)" :)
 
S

Steve Holden

Roy said:
Well, before you can "add three months" to something, you need to explain
what that means.

What is Nov 29th plus 3 months?

What is Jan 31st plus 3 months?

Months are different lengths. Asking to "add 3 months" is kind of like
asking, "If I'm somewhere in the continental US (east of the Mississippi
River) and move three states to the west, how many miles have I moved?"
OK, suppose I sign a contract on Nov 30 that requires me to make
quarterly payments. When is my next payment due?

The use case doesn't seem that unreasonable to me.

regards
Steve
 
C

Chris Rebert

OK, suppose I sign a contract on Nov 30 that requires me to make
quarterly payments. When is my next payment due?

The use case doesn't seem that unreasonable to me.

Indeed, but the point is that there are likewise reasonable usecases
for the other behaviors too and one should refuse to guess in the face
of ambiguity; the std lib has, merely by default in this case, taken
this to the extreme of not implementing any of them directly.

Somewhat unrelated wish: if only dateutil were in the std lib... Alas!

Cheers,
Chris
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top