views:

520

answers:

3

The Python datetime.isocalendar() method returns a tuple (ISO_year, ISO_week_number, ISO_weekday) for the given datetime object. Is there a corresponding inverse function? If not, is there an easy way to compute a date given a year, week number and day of the week?

+1  A: 

EDIT: ignore this, the edge cases are a pain. Go with Ben's solution.

Ok, on closer inspection I noticed that strptime has %W and %w parameters, so the following works:

def fromisocalendar(y,w,d):
   return datetime.strptime( "%04dW%02d-%d"%(y,w-1,d), "%YW%W-%w")

A couple of gotchas: The ISO week number starts at 1, while %W starts at 0. The ISO week day starts at 1 (Monday), which is the same as %w, so Sunday would probably have to be 0, not 7...

Tom
Which version are you using?, I was testing on 2.4.2 and didn't work for me, found http://bugs.python.org/issue1045381 but says it's done on 2.3
Vinko Vrsalovic
I'm using 2.5.2, %W is working, not sure about %U.
Tom
This looks like you answered it. Why not accept your answer?
S.Lott
AFAIK S.O. won't let you accept your own answers...
Tom
@Tom: S.O. does let you accept your own answers. See this discussion on meta: http://meta.stackoverflow.com/questions/9933/is-there-a-convention-for-accepting-my-own-answer-to-my-own-question
GreenMatt
@GreenMatt, yeah, that feature's new since I made that comment. And this answer isn't as good as Ben's anyway.
Tom
@Tom: Oops! Didn't catch that this was from '08.
GreenMatt
+1  A: 

Note that %W is the week # (0-53) which is NOT THE SAME as the ISO week (1-53). There will be edge cases where %W will not work.

I sort of noted that in my answer above, any chance you could expand on what those edge cases would be?
Tom
+4  A: 

I recently had to solve this problem myself, and came up with this solution:

import datetime

def iso_year_start(iso_year):
    "The gregorian calendar date of the first day of the given ISO year"
    fourth_jan = datetime.date(iso_year, 1, 4)
    delta = datetime.timedelta(fourth_jan.isoweekday()-1)
    return fourth_jan - delta 

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    year_start = iso_year_start(iso_year)
    return year_start + datetime.timedelta(iso_day-1, 0, 0, 0, 0, 0, iso_week-1)

A few test cases:

>>> iso = datetime.date(2005, 1, 1).isocalendar()
>>> iso
(2004, 53, 6)
>>> iso_to_gregorian(*iso)
datetime.date(2005, 1, 1)

>>> iso = datetime.date(2010, 1, 4).isocalendar()    
>>> iso
(2010, 1, 1)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 4)

>>> iso = datetime.date(2010, 1, 3).isocalendar()
>>> iso
(2009, 53, 7)
>>> iso_to_gregorian(*iso)
datetime.date(2010, 1, 3)
Ben James
Can you clarify the significance of the 4th of January? Is there a description of the ISO calendar standard somewhere that's appropriate?
Tom
Tom: from the formal ISO definition of week 1 (the week containing the first Thursday of the year) it follows that 4th January is the latest that week 1 can start.
Ben James
http://en.wikipedia.org/wiki/ISO_week_date
Tom