Finding week of year with week ending on Saturday and first week containing atleast 4 days, in python

StackOverflow https://stackoverflow.com/questions/16765097

Question

For a given date, I have to find the week number of the year, following these rules:

  1. Week starts on Sunday and ends on Saturday.
  2. The first week of the year ends on the first Saturday of January, as long as it falls at least four days into the month, even if it means that the first week starts in December.

I know that the datetime.datetime.isocalendar() returns a similar results but there the week starts on Monday. The time.strftime('%U',<tuple>) module returns the week number with week starting on Sunday, but it considers the first week of the year as the one ending on the first Saturday (w/o consideration for minimum 4 days of the week being in Jan). Is there a module which can let me find the week number according to my definition above? Otherwise can someone suggest a way to overload the datetime.isocalendar()

Edit: I was trying the following method

Step 1: Find the first week of the year, counting weeks from Sunday and not considering the 4 days restriction (basically the first week should contain the first Wednesday of the year).

I used

dt = datetime.date.today()
year = dt.year 
first_Sunday = datetime.datetime.strptime('%d-00-0' % year, '%Y-%U-%w').date()

Step 2: Determine whether the first week so obtain contains the first Wednesday or not.

However for some strange reason datetime.datetime.strptime('2013-00-0', '%Y-%U-%w').date() is outputting date(2013, 1, 1) which is clearly a Tuesday!!

Was it helpful?

Solution

Since you know roughly when it will fall, the easiest way to find the first week might be to do a linear search for it. By the rules you give, the end of the week will fall on the first Saturday on or after the 4th of January. You can find this by:

def first_saturday(year):
     candidate = dt.datetime(year, 1, 4)
     day = dt.timedelta(days=1)
     while candidate.weekday() != 6:
         candidate += day
     return candidate

If you wanted, you could make this read a bit nicer by implementing a datecount function analgous to itertools.count, so that you have:

first_saturday = next(day for day in 
   datecount(datetime(year, 1, 4), timedelta(days=1)) 
   if day.weekday() == 6)

From there, find the starting Sunday by subtracting 6 days from the starting Saturday. Then the number of weeks should be:

(arbitrary_day - first_sunday) // timedelta(days=7)

This will count from zero.

To find out which year a particular day belongs in, there are only three possibilities: its gregorian calendar year, the year after, or the year before. The one you're interested in is the lowest of those three where first_sunday(year) <= arbitrary_date.

OTHER TIPS

The actual datetime module is written in c so overiding is not really an option AFAIK. Double check my logic, but I think you are looking for something like this.

def getWeekNumber(date):
     year,week,day = date.isocalendar()
     jan_1 = datetime.date(year=year,month=1,day=1)
     if jan_1.weekday()==3: //if jan 1 is a thursday, there is one less week 
         week-=1
     if day == 7: #Add a week if it is Sunday as its actually in the next week
         week+=1
     if week==53: #week 53 is actually week 0 of next year
         week = 0

     return week

The basic logic here is that in isocalendar, jan 1 has to be a thursday or less for it to count as week one, in the format you are after it has to be a wednesday or less. The outside case is when its thursday jan 1 -> reduce week by 1.

Push all sundays into the next week.

If pushing creates a week 53, change week to 0(as week 53 is actually in next year)

Again, this is untested.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top