[CalendarServer-changes] [11226] PyCalendar/trunk/src/pycalendar
source_changes at macosforge.org
source_changes at macosforge.org
Tue May 21 06:40:40 PDT 2013
Revision: 11226
http://trac.calendarserver.org//changeset/11226
Author: cdaboo at apple.com
Date: 2013-05-21 06:40:40 -0700 (Tue, 21 May 2013)
Log Message:
-----------
Fix week number handling in date class so that BYWEEKNO recurrence works.
Modified Paths:
--------------
PyCalendar/trunk/src/pycalendar/datetime.py
PyCalendar/trunk/src/pycalendar/recurrence.py
PyCalendar/trunk/src/pycalendar/tests/test_datetime.py
PyCalendar/trunk/src/pycalendar/tests/test_recurrence.py
Modified: PyCalendar/trunk/src/pycalendar/datetime.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/datetime.py 2013-05-21 13:35:26 UTC (rev 11225)
+++ PyCalendar/trunk/src/pycalendar/datetime.py 2013-05-21 13:40:40 UTC (rev 11226)
@@ -412,37 +412,73 @@
def setWeekNo(self, weekno):
- # This is the iso 8601 week number definition
+ """
+ Set the current date to one with the same day of the week in the current year with the
+ specified week number. Note this might cause the year to shift backwards or forwards
+ if the date is at the boundary between two years.
- # What day does the current year start on
+ @param weekno: the week number to set (currently must be positive)
+ @type weekno: C{int}
+ """
+
+ # Don't both if already correct
+ if self.getWeekNo() == weekno:
+ return
+
+ # What day does the current year start on, and diff that with the current day
temp = PyCalendarDateTime(year=self.mYear, month=1, day=1)
first_day = temp.getDayOfWeek()
+ current_day = self.getDayOfWeek()
- # Calculate and set yearday for start of week
- if (first_day == PyCalendarDateTime.SUNDAY) or (first_day == PyCalendarDateTime.MONDAY) or \
- (first_day == PyCalendarDateTime.TUESDAY) or (first_day == PyCalendarDateTime.WEDNESDAY) or (first_day == PyCalendarDateTime.THURSDAY):
- self.setYearDay((weekno - 1) * 7 - first_day)
- elif (first_day == PyCalendarDateTime.FRIDAY) or (first_day == PyCalendarDateTime.SATURDAY):
- self.setYearDay((weekno - 1) * 7 - first_day + 7)
+ # Calculate and set yearday for start of week. The first week is the one that contains at least
+ # four days (with week start defaulting to MONDAY), so that means the 1st of January would fall
+ # on MO, TU, WE, TH.
+ if first_day in (PyCalendarDateTime.MONDAY, PyCalendarDateTime.TUESDAY, PyCalendarDateTime.WEDNESDAY, PyCalendarDateTime.THURSDAY):
+ year_day = (weekno - 1) * 7 + current_day - first_day
+ else:
+ year_day = weekno * 7 + current_day - first_day
+ # It is possible we have a negative offset which means go back to the prior year as part of
+ # week #1 exists at the end of that year.
+ if year_day < 0:
+ self.offsetYear(-1)
+ else:
+ year_day += 1
+ self.setYearDay(year_day)
+
def getWeekNo(self):
- # This is the iso 8601 week number definition
+ """
+ Return the ISO week number for the current date.
+ """
# What day does the current year start on
temp = PyCalendarDateTime(year=self.mYear, month=1, day=1)
first_day = temp.getDayOfWeek()
+ if first_day == 0:
+ first_day = 7
+ current_day = self.getDayOfWeek()
+ if current_day == 0:
+ current_day = 7
- # Get days upto the current one
- yearday = self.getYearDay()
+ # This arithmetic uses the ISO day of week (1-7) and the year day to get the week number
+ week_no = (self.getYearDay() - current_day + 10) / 7
- if (first_day == PyCalendarDateTime.SUNDAY) or (first_day == PyCalendarDateTime.MONDAY) or \
- (first_day == PyCalendarDateTime.TUESDAY) or (first_day == PyCalendarDateTime.WEDNESDAY) or (first_day == PyCalendarDateTime.THURSDAY):
- return (yearday + first_day) / 7 + 1
- elif (first_day == PyCalendarDateTime.FRIDAY) or (first_day == PyCalendarDateTime.SATURDAY):
- return (yearday + first_day - 7) / 7 + 1
+ # Might need to adjust forward/backwards based on year boundaries
+ if week_no == 0:
+ # Last week of previous year
+ temp = PyCalendarDateTime(year=self.mYear - 1, month=12, day=31)
+ week_no = temp.getWeekNo()
+ elif week_no == 53:
+ # Might be first week of next year
+ temp = PyCalendarDateTime(year=self.mYear + 1, month=1, day=1)
+ first_day = temp.getDayOfWeek()
+ if first_day in (PyCalendarDateTime.MONDAY, PyCalendarDateTime.TUESDAY, PyCalendarDateTime.WEDNESDAY, PyCalendarDateTime.THURSDAY):
+ week_no = 1
+ return week_no
+
def isWeekNo(self, weekno):
# This is the iso 8601 week number definition
Modified: PyCalendar/trunk/src/pycalendar/recurrence.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/recurrence.py 2013-05-21 13:35:26 UTC (rev 11225)
+++ PyCalendar/trunk/src/pycalendar/recurrence.py 2013-05-21 13:40:40 UTC (rev 11226)
@@ -884,7 +884,6 @@
float_until.offsetSeconds(float_offset)
# Always add the initial instance DTSTART
- items.append(start.duplicate())
if self.mUseCount:
# Bump counter and exit if over
ctr += 1
Modified: PyCalendar/trunk/src/pycalendar/tests/test_datetime.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/tests/test_datetime.py 2013-05-21 13:35:26 UTC (rev 11225)
+++ PyCalendar/trunk/src/pycalendar/tests/test_datetime.py 2013-05-21 13:40:40 UTC (rev 11226)
@@ -322,3 +322,51 @@
self.assertTrue(dt2.mPosixTimeCached)
self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
self.assertEqual(dt2.mTZOffset, 0)
+
+
+ def testSetWeekNo(self):
+
+ dt = PyCalendarDateTime(2013, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 1)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2013, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
+
+ dt = PyCalendarDateTime(2013, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 1)
+ dt.setWeekNo(2)
+ self.assertEqual(dt, PyCalendarDateTime(2013, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 2)
+
+ dt = PyCalendarDateTime(2013, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 2)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2013, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
+
+ dt = PyCalendarDateTime(2014, 1, 7, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 2)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2013, 12, 31, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
+
+ dt = PyCalendarDateTime(2012, 12, 31, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 1)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2012, 12, 31, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
+
+ dt = PyCalendarDateTime(2016, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 53)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2016, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
+ dt.setWeekNo(2)
+ self.assertEqual(dt, PyCalendarDateTime(2016, 1, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 2)
+
+ dt = PyCalendarDateTime(2016, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
+ self.assertEqual(dt.getWeekNo(), 1)
+ dt.setWeekNo(1)
+ self.assertEqual(dt, PyCalendarDateTime(2016, 1, 8, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
+ self.assertEqual(dt.getWeekNo(), 1)
Modified: PyCalendar/trunk/src/pycalendar/tests/test_recurrence.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/tests/test_recurrence.py 2013-05-21 13:35:26 UTC (rev 11225)
+++ PyCalendar/trunk/src/pycalendar/tests/test_recurrence.py 2013-05-21 13:40:40 UTC (rev 11226)
@@ -14,6 +14,8 @@
# limitations under the License.
##
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.period import PyCalendarPeriod
from pycalendar.recurrence import PyCalendarRecurrence
import unittest
@@ -111,3 +113,28 @@
hashes.sort()
for i in range(1, len(hashes)):
self.assertNotEqual(hashes[i - 1], hashes[i])
+
+
+ def testByWeekNoExpand(self):
+
+ recur = PyCalendarRecurrence()
+ recur.parse("FREQ=YEARLY;BYWEEKNO=1,2")
+ start = PyCalendarDateTime(2013, 1, 1, 0, 0, 0)
+ end = PyCalendarDateTime(2017, 1, 1, 0, 0, 0)
+ items = []
+ range = PyCalendarPeriod(start, end)
+ recur.expand(start, range, items)
+ self.assertEqual(
+ items,
+ [
+ PyCalendarDateTime(2013, 1, 1, 0, 0, 0),
+ PyCalendarDateTime(2013, 1, 8, 0, 0, 0),
+ PyCalendarDateTime(2014, 1, 1, 0, 0, 0),
+ PyCalendarDateTime(2014, 1, 8, 0, 0, 0),
+ PyCalendarDateTime(2015, 1, 1, 0, 0, 0),
+ PyCalendarDateTime(2015, 1, 8, 0, 0, 0),
+ PyCalendarDateTime(2016, 1, 8, 0, 0, 0),
+ PyCalendarDateTime(2016, 1, 15, 0, 0, 0),
+ ],
+ )
+ print items
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130521/c3e42fed/attachment-0001.html>
More information about the calendarserver-changes
mailing list