<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[14193] PyCalendar/trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/14193">14193</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2014-12-01 08:50:49 -0800 (Mon, 01 Dec 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Undo <a href="http://trac.calendarserver.org//changeset/14191">r14191</a> which was meant to go on a branch.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#PyCalendartrunkproject">PyCalendar/trunk/.project</a></li>
<li><a href="#PyCalendartrunksrcpycalendardatetimepy">PyCalendar/trunk/src/pycalendar/datetime.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendardefinitionspy">PyCalendar/trunk/src/pycalendar/icalendar/definitions.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarrecurrencepy">PyCalendar/trunk/src/pycalendar/icalendar/recurrence.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarteststest_recurrencepy">PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recurrence.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarxmldefinitionspy">PyCalendar/trunk/src/pycalendar/icalendar/xmldefinitions.py</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#PyCalendartrunksrcpycalendaricalendaricudatetimepy">PyCalendar/trunk/src/pycalendar/icalendar/icudatetime.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarrecuriterpy">PyCalendar/trunk/src/pycalendar/icalendar/recuriter.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarteststest_icudatetimepy">PyCalendar/trunk/src/pycalendar/icalendar/tests/test_icudatetime.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendaricalendarteststest_recuriterpy">PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recuriter.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="PyCalendartrunkproject"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/.project (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/.project        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/.project        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx">         <name>pycalendar</name>
</span><span class="cx">         <comment></comment>
</span><span class="cx">         <projects>
</span><del>-                <project>cffi</project>
</del><span class="cx">         </projects>
</span><span class="cx">         <buildSpec>
</span><span class="cx">                 <buildCommand>
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendardatetimepy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/datetime.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/datetime.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/datetime.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -301,7 +301,7 @@
</span><span class="cx"> self.changed()
</span><span class="cx">
</span><span class="cx">
</span><del>- def setYYMMDD(self, year, month, days, isleapmonth=False):
</del><ins>+ def setYYMMDD(self, year, month, days):
</ins><span class="cx"> if (self.mYear != year) or (self.mMonth != month) or (self.mDay != days):
</span><span class="cx"> self.mYear = year
</span><span class="cx"> self.mMonth = month
</span><span class="lines">@@ -321,18 +321,14 @@
</span><span class="cx">
</span><span class="cx"> def offsetYear(self, diff_year):
</span><span class="cx"> self.mYear += diff_year
</span><ins>+ self.normalise()
</ins><span class="cx">
</span><del>- # Do special normalization for this case to do a skip backwards if
- # the new date is invalid
- if self.mDay > utils.daysInMonth(self.mMonth, self.mYear):
- self.mDay = utils.daysInMonth(self.mMonth, self.mYear)
</del><span class="cx">
</span><del>-
</del><span class="cx"> def getMonth(self):
</span><span class="cx"> return self.mMonth
</span><span class="cx">
</span><span class="cx">
</span><del>- def setMonth(self, month, isleapmonth=False):
</del><ins>+ def setMonth(self, month):
</ins><span class="cx"> if self.mMonth != month:
</span><span class="cx"> self.mMonth = month
</span><span class="cx"> self.changed()
</span><span class="lines">@@ -340,26 +336,9 @@
</span><span class="cx">
</span><span class="cx"> def offsetMonth(self, diff_month):
</span><span class="cx"> self.mMonth += diff_month
</span><ins>+ self.normalise()
</ins><span class="cx">
</span><del>- # Normalise month
- normalised_month = ((self.mMonth - 1) % 12) + 1
- adjustment_year = (self.mMonth - 1) / 12
- if (normalised_month - 1) < 0:
- normalised_month += 12
- adjustment_year -= 1
- self.mMonth = normalised_month
- self.mYear += adjustment_year
</del><span class="cx">
</span><del>- # Do special normalization for this case to do a skip backwards if
- # the new date is invalid
- if self.mDay > utils.daysInMonth(self.mMonth, self.mYear):
- self.mDay = utils.daysInMonth(self.mMonth, self.mYear)
-
-
- def getLeapMonth(self):
- return False
-
-
</del><span class="cx"> def getDay(self):
</span><span class="cx"> return self.mDay
</span><span class="cx">
</span><span class="lines">@@ -465,22 +444,16 @@
</span><span class="cx"> # What day does the current year start on, and diff that with the current day
</span><span class="cx"> temp = DateTime(year=self.mYear, month=1, day=1)
</span><span class="cx"> first_day = temp.getDayOfWeek()
</span><del>- if first_day == 0:
- first_day = 7
</del><span class="cx"> current_day = self.getDayOfWeek()
</span><del>- if current_day == 0:
- current_day = 7
</del><span class="cx">
</span><span class="cx"> # Calculate and set yearday for start of week. The first week is the one that contains at least
</span><span class="cx"> # four days (with week start defaulting to MONDAY), so that means the 1st of January would fall
</span><span class="cx"> # on MO, TU, WE, TH.
</span><span class="cx"> if first_day in (DateTime.MONDAY, DateTime.TUESDAY, DateTime.WEDNESDAY, DateTime.THURSDAY):
</span><del>- offset = 0
</del><ins>+ year_day = (weekno - 1) * 7 + current_day - first_day
</ins><span class="cx"> else:
</span><del>- offset = 1
</del><ins>+ year_day = weekno * 7 + current_day - first_day
</ins><span class="cx">
</span><del>- year_day = (weekno - 1 + offset) * 7 + current_day - first_day
-
</del><span class="cx"> # It is possible we have a negative offset which means go back to the prior year as part of
</span><span class="cx"> # week #1 exists at the end of that year.
</span><span class="cx"> if year_day < 0:
</span><span class="lines">@@ -1170,16 +1143,6 @@
</span><span class="cx"> jobject.append(self.getJSONText())
</span><span class="cx">
</span><span class="cx">
</span><del>- # When doing recurrence iteration we sometimes need to preserve an invalid value for
- # either day or month (though month is never invalid for Gregorian calendars it can
- # be for non-Gregorian). For this class we simply set the stored attributes to their
- # invalid values.
- def setInvalid(self, year, month, day, isleapmonth=False):
- self.mYear = year
- self.mMonth = month
- self.mDay = day
-
-
</del><span class="cx"> def invalid(self):
</span><span class="cx"> """
</span><span class="cx"> Are any of the current fields invalid.
</span><span class="lines">@@ -1194,32 +1157,6 @@
</span><span class="cx"> return False
</span><span class="cx">
</span><span class="cx">
</span><del>- def invalidSkip(self, skip):
- """
- If this is an invalid value skip backward or forward or not at all.
-
- @param skip: the skip mode (yes, backward, forward)
- @type skip: L{int}
- """
-
- if self.invalid():
- if skip == definitions.eRecurrence_SKIP_YES:
- # Leave it as invalid
- pass
- elif skip == definitions.eRecurrence_SKIP_BACKWARD:
- if self.mDay <= 0:
- self.mDay = 1
- self.offsetDay(-1)
- else:
- self.mDay = utils.daysInMonth(self.mMonth, self.mYear)
- elif skip == definitions.eRecurrence_SKIP_FORWARD:
- if self.mDay <= 0:
- self.mDay = 1
- else:
- self.mDay = utils.daysInMonth(self.mMonth, self.mYear)
- self.offsetDay(1)
-
-
</del><span class="cx"> def normalise(self):
</span><span class="cx"> # Normalise seconds
</span><span class="cx"> normalised_secs = self.mSeconds % 60
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendardefinitionspy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/icalendar/definitions.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/definitions.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/definitions.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -230,8 +230,6 @@
</span><span class="cx"> eRecurrence_BYMONTH = 11
</span><span class="cx"> eRecurrence_BYSETPOS = 12
</span><span class="cx"> eRecurrence_WKST = 13
</span><del>-eRecurrence_RSCALE = 14
-eRecurrence_SKIP = 15
</del><span class="cx">
</span><span class="cx"> cICalValue_RECUR_FREQ = "FREQ"
</span><span class="cx"> cICalValue_RECUR_FREQ_LEN = 5
</span><span class="lines">@@ -258,8 +256,6 @@
</span><span class="cx"> cICalValue_RECUR_BYMONTH = "BYMONTH"
</span><span class="cx"> cICalValue_RECUR_BYSETPOS = "BYSETPOS"
</span><span class="cx"> cICalValue_RECUR_WKST = "WKST"
</span><del>-cICalValue_RECUR_RSCALE = "RSCALE"
-cICalValue_RECUR_SKIP = "SKIP"
</del><span class="cx">
</span><span class="cx"> eRecurrence_WEEKDAY_SU = 0
</span><span class="cx"> eRecurrence_WEEKDAY_MO = 1
</span><span class="lines">@@ -277,14 +273,6 @@
</span><span class="cx"> cICalValue_RECUR_WEEKDAY_FR = "FR"
</span><span class="cx"> cICalValue_RECUR_WEEKDAY_SA = "SA"
</span><span class="cx">
</span><del>-eRecurrence_SKIP_YES = 0
-eRecurrence_SKIP_BACKWARD = 1
-eRecurrence_SKIP_FORWARD = 2
-
-cICalValue_RECUR_SKIP_YES = "YES"
-cICalValue_RECUR_SKIP_BACKWARD = "BACKWARD"
-cICalValue_RECUR_SKIP_FORWARD = "FORWARD"
-
</del><span class="cx"> # 5545 Section 3.8.1.11
</span><span class="cx"> eStatus_VEvent_None = 0
</span><span class="cx"> eStatus_VEvent_Confirmed = 1
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendaricudatetimepy"></a>
<div class="delfile"><h4>Deleted: PyCalendar/trunk/src/pycalendar/icalendar/icudatetime.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/icudatetime.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/icudatetime.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -1,1005 +0,0 @@
</span><del>-##
-# Copyright (c) 2014 Cyrus Daboo. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from cffi import FFI
-from __builtin__ import classmethod
-from pycalendar.datetime import DateTime
-from pycalendar.icalendar import definitions
-
-# Use cffi to get access to libicucore functions and constants
-ffi = FFI()
-hdr = """
- //#define U_FAILURE(x) ((x)>U_ZERO_ERROR)
-
- typedef double UDate;
- UDate ucal_getNow (void);
-
- typedef void * UCalendar;
- typedef uint16_t UChar;
- enum UCalendarType { UCAL_TRADITIONAL=0, UCAL_DEFAULT=0, UCAL_GREGORIAN, ... };
- typedef enum UCalendarType UCalendarType;
- enum UErrorCode {
- U_ZERO_ERROR = 0
- };
- typedef enum UErrorCode UErrorCode;
-
- enum UCalendarDaysOfWeek {
- /** Sunday */
- UCAL_SUNDAY = 1,
- /** Monday */
- UCAL_MONDAY,
- /** Tuesday */
- UCAL_TUESDAY,
- /** Wednesday */
- UCAL_WEDNESDAY,
- /** Thursday */
- UCAL_THURSDAY,
- /** Friday */
- UCAL_FRIDAY,
- /** Saturday */
- UCAL_SATURDAY
- };
-
- typedef enum UCalendarDaysOfWeek UCalendarDaysOfWeek;
-
- enum UCalendarDateFields {
- UCAL_ERA,
- UCAL_YEAR,
- UCAL_MONTH,
- UCAL_WEEK_OF_YEAR,
- UCAL_WEEK_OF_MONTH,
- UCAL_DATE,
- UCAL_DAY_OF_YEAR,
- UCAL_DAY_OF_WEEK,
- UCAL_DAY_OF_WEEK_IN_MONTH,
- UCAL_AM_PM,
- UCAL_HOUR,
- UCAL_HOUR_OF_DAY,
- UCAL_MINUTE,
- UCAL_SECOND,
- UCAL_MILLISECOND,
- UCAL_ZONE_OFFSET,
- UCAL_DST_OFFSET,
- UCAL_YEAR_WOY,
- UCAL_DOW_LOCAL,
- UCAL_EXTENDED_YEAR,
- UCAL_JULIAN_DAY,
- UCAL_MILLISECONDS_IN_DAY,
- UCAL_IS_LEAP_MONTH,
- UCAL_FIELD_COUNT,
- UCAL_DAY_OF_MONTH=5
- };
-
- typedef enum UCalendarDateFields UCalendarDateFields;
-
- enum UCalendarMonths {
- /** January */
- UCAL_JANUARY,
- /** February */
- UCAL_FEBRUARY,
- /** March */
- UCAL_MARCH,
- /** April */
- UCAL_APRIL,
- /** May */
- UCAL_MAY,
- /** June */
- UCAL_JUNE,
- /** July */
- UCAL_JULY,
- /** August */
- UCAL_AUGUST,
- /** September */
- UCAL_SEPTEMBER,
- /** October */
- UCAL_OCTOBER,
- /** November */
- UCAL_NOVEMBER,
- /** December */
- UCAL_DECEMBER,
- /** Value of the <code>UCAL_MONTH</code> field indicating the
- * thirteenth month of the year. Although the Gregorian calendar
- * does not use this value, lunar calendars do.
- */
- UCAL_UNDECIMBER
- };
- typedef enum UCalendarMonths UCalendarMonths;
-
- UCalendar * ucal_open(const UChar *zoneID, int32_t len, const char *locale, UCalendarType type, UErrorCode *status);
- void ucal_close(UCalendar *cal);
- UCalendar * ucal_clone(const UCalendar* cal, UErrorCode* status);
- void ucal_setDate(UCalendar *cal, int32_t year, int32_t month, int32_t date, UErrorCode *status);
-
- const char* ucal_getTZDataVersion (UErrorCode *status);
-
- UDate ucal_getMillis(const UCalendar* cal,
- UErrorCode* status);
- void ucal_setMillis(UCalendar* cal,
- UDate dateTime,
- UErrorCode* status);
-
- int32_t ucal_get(const UCalendar* cal,
- UCalendarDateFields field,
- UErrorCode* status);
- void ucal_set(UCalendar* cal,
- UCalendarDateFields field,
- int32_t value);
- void ucal_add(UCalendar* cal,
- UCalendarDateFields field,
- int32_t amount,
- UErrorCode* status);
-
- enum UCalendarLimitType {
- /** Minimum value */
- UCAL_MINIMUM,
- /** Maximum value */
- UCAL_MAXIMUM,
- /** Greatest minimum value */
- UCAL_GREATEST_MINIMUM,
- /** Leaest maximum value */
- UCAL_LEAST_MAXIMUM,
- /** Actual minimum value */
- UCAL_ACTUAL_MINIMUM,
- /** Actual maximum value */
- UCAL_ACTUAL_MAXIMUM
- };
-
- typedef enum UCalendarLimitType UCalendarLimitType;
-
- int32_t ucal_getLimit(const UCalendar* cal,
- UCalendarDateFields field,
- UCalendarLimitType type,
- UErrorCode* status);
-"""
-
-ffi.cdef(hdr)
-ffi.verify(hdr.replace(", ...", ""))
-
-ICU = ffi.dlopen("libicucore")
-
-class ICUDateTime(object):
- """
- An ICU-based L{DateTime} like class that supports non-Gregorian date-time values and arithmetic.
- """
-
- RSCALE_GREGORIAN = "gregorian"
- RSCALE_HEBREW = "hebrew"
-
- RSCALE_CALCODE = {
- "gregorian": "",
- "chinese": "C",
- "islamic-civil": "I",
- "hebrew": "H",
- "ethiopic": "E",
- }
-
- def __init__(self, rscale, ucal):
- """
- Initialize using an ICU C{ucal} object and the name of the calendar scale.
-
- @param rscale: calendar scale being used
- @type rscale: L{str}
- @param ucal: ICU ucal object
- @type ucal: L{ICU.UCalendar*}
- """
- self.rscale = rscale
- self.ucal = ucal
-
- self.mHours = 0
- self.mMinutes = 0
- self.mSeconds = 0
-
- self.mDateOnly = True
-
- self.mTZUTC = False
- self.mTZID = None
- self.mTZOffset = None
-
- self.mInvalid = None
-
-
- def __del__(self):
- """
- Always close the ICU C{ucal} object.
- """
- ICU.ucal_close(self.ucal)
- self.ucal = None
-
-
- def duplicate(self):
- """
- Duplicate this object.
- """
-
- error = ffi.new("UErrorCode *", 0)
- clone = ICU.ucal_clone(self.ucal, error)
- dup = ICUDateTime(self.rscale, clone)
- dup._transferHHMMSS(self, dup)
- dup.mInvalid = self.mInvalid
-
- return dup
-
-
- def __repr__(self):
- return "ICUDateTime: %s" % (self.getText(),)
-
-
- def __hash__(self):
- return hash(self.getPosixTime())
-
-
- @classmethod
- def fromDateTime(cls, dt, rscale):
- """
- Convert from a regular L{DateTime} to the specified calendar scale.
-
- @param dt: the regular value to convert from
- @type dt: L{DateTime}
- @param rscale: the calendar scale to convert to
- @type rscale: L{str}
-
- @return: the new ICU object
- @rtyope: L{ICUDateTime}
- """
-
- # Try to create the ICU object that represents this date
- gregorian = cls.fromDateComponents(cls.RSCALE_GREGORIAN, dt.getYear(), dt.getMonth(), dt.getDay())
- cls._transferHHMMSS(dt, gregorian)
- return gregorian.convertTo(rscale)
-
-
- def toDateTime(self):
- """
- Convert to a regular L{DateTime}.
-
- @return: the converted object
- @rtype: L{DateTime}
- """
-
- # Try to create the ICU object that represents this date
- gregorian = self if self.rscale.lower() == self.RSCALE_GREGORIAN else self.convertTo(self.RSCALE_GREGORIAN)
- dt = DateTime(gregorian.getYear(), gregorian.getMonth(), gregorian.getDay())
- self._transferHHMMSS(self, dt)
- return dt
-
-
- @classmethod
- def _newUcal(cls, rscale):
- """
- Create an ICU C{ucal} object for the specified calendar scale.
-
- @param rscale: calendar scale to use
- @type rscale: L{str}
-
- @return: the ICU ucal object
- @rtype: L{ICU.UCalendar*}
- """
- calsystem = "*@calendar={}".format(rscale)
- error = ffi.new("UErrorCode *", 0)
- ucal = ICU.ucal_open(ffi.NULL, -1, ffi.new("char[]", calsystem), ICU.UCAL_DEFAULT, error)
- if error[0] != ICU.U_ZERO_ERROR:
- raise ValueError("Unable to create ICU calendar for rscale '{}', code: {}".format(rscale, error))
- return ucal
-
-
- @classmethod
- def fromDateComponents(cls, rscale, year, month, day, isleapmonth=False):
- """
- Create ICU calendar for the specified calendar scale with the specified components.
-
- @param dt: the regular value to convert from
- @type dt: L{DateTime}
- @param rscale: the calendar scale to convert to
- @type rscale: L{str}
- @param year: the year component
- @type year: L{int}
- @param month: the month component
- @type month: L{int}
- @param day: the day component
- @type day: L{int}
- @param isleapmonth: the leap month component
- @type isleapmonth: L{bool}
-
- @return: the new object
- @rtype: L{ICUDateTime}
- """
-
- # Try to create the ICU object that represents this date
- ucal = cls._newUcal(rscale)
-
- month, isleapmonth = cls._adjustToICULeapMonth(rscale, month, isleapmonth)
-
- ICU.ucal_set(ucal, ICU.UCAL_EXTENDED_YEAR, year)
- ICU.ucal_set(ucal, ICU.UCAL_MONTH, cls._numericMonthToICU(month))
- ICU.ucal_set(ucal, ICU.UCAL_DAY_OF_MONTH, day)
- ICU.ucal_set(ucal, ICU.UCAL_IS_LEAP_MONTH, isleapmonth)
-
- return ICUDateTime(rscale, ucal)
-
-
- @classmethod
- def _numericMonthToICU(cls, month):
- """
- Map our month numbers (1..13) to ICU constants.
-
- @param month: the month to map
- @type month: L{int}
-
- @return: the ICU constant
- @rtype: L{ICU.UCalendarMonths}
- """
- return {
- 1: ICU.UCAL_JANUARY,
- 2: ICU.UCAL_FEBRUARY,
- 3: ICU.UCAL_MARCH,
- 4: ICU.UCAL_APRIL,
- 5: ICU.UCAL_MAY,
- 6: ICU.UCAL_JUNE,
- 7: ICU.UCAL_JULY,
- 8: ICU.UCAL_AUGUST,
- 9: ICU.UCAL_SEPTEMBER,
- 10: ICU.UCAL_OCTOBER,
- 11: ICU.UCAL_NOVEMBER,
- 12: ICU.UCAL_DECEMBER,
- 13: ICU.UCAL_UNDECIMBER,
- }[month]
-
-
- @classmethod
- def _icuToNumericMonth(cls, month):
- """
- Map ICU constants to our month numbers (1..13).
-
- @param month: the ICU constant to map
- @type month: L{ICU.UCalendarMonths}
-
- @return: the month
- @rtype: L{int}
- """
- return {
- ICU.UCAL_JANUARY: 1,
- ICU.UCAL_FEBRUARY: 2,
- ICU.UCAL_MARCH: 3,
- ICU.UCAL_APRIL: 4,
- ICU.UCAL_MAY: 5,
- ICU.UCAL_JUNE: 6,
- ICU.UCAL_JULY: 7,
- ICU.UCAL_AUGUST: 8,
- ICU.UCAL_SEPTEMBER: 9,
- ICU.UCAL_OCTOBER: 10,
- ICU.UCAL_NOVEMBER: 11,
- ICU.UCAL_DECEMBER: 12,
- ICU.UCAL_UNDECIMBER: 13,
- }[month]
-
-
- @classmethod
- def _adjustToICULeapMonth(cls, rscale, month, isleapmonth):
- """
- For the Hebrew calendar, ICU uses a count of 13 months rather than 12 months
- plus an "isleapmonth" indicator. So when converting to/from ICU we need to make
- that adjustment as we always use 12 months + isleapmonth. This method converts
- from our internal representation to what ICU uses.
-
- @param rscale: calendar scale to convert to
- @type rscale: L{str}
- @param month: month number (12 month cycle)
- @type month: L{int}
- @param isleapmonth: is leap month indicator
- @type isleapmonth: L{bool} of L{None}
-
- @return: a tuple of the ICU-mapped month number and isleapmonth indicator
- @rtype: L{tuple} of (L{int}, L{bool}
- """
-
- if rscale.lower() == cls.RSCALE_HEBREW:
- if month == 5 and isleapmonth:
- month = 6
- isleapmonth = None
- elif month >= 6:
- month += 1
- return (month, isleapmonth,)
-
-
- @classmethod
- def _adjustFromICULeapMonth(cls, rscale, month, isleapmonth):
- """
- For the Hebrew calendar, ISU uses a count of 13 months rather than 12 months
- plus an "isleapmonth" indicator. So when converting to/from ICU we need to make
- that adjustment as we always use 12 months + isleapmonth. This method converts
- to our internal representation from what ICU uses.
-
- @param rscale: calendar scale to convert from
- @type rscale: L{str}
- @param month: month number (13 month cycle)
- @type month: L{int}
- @param isleapmonth: is leap month indicator
- @type isleapmonth: L{bool} of L{None}
-
- @return: a tuple of the month number and isleapmonth indicator
- @rtype: L{tuple} of (L{int}, L{bool}
- """
-
- if rscale.lower() == cls.RSCALE_HEBREW:
- isleapmonth = False
- if month == 6:
- isleapmonth = True
- elif month >= 6:
- month -= 1
- return (month, isleapmonth,)
-
-
- @classmethod
- def _transferHHMMSS(cls, from_dt, to_dt):
- """
- Transfer the time and timezone components from one L{ICUDateTime} to another.
-
- @param from_dt: object to copy from
- @type from_dt: L{ICUDateTime}
- @param to_dt: object to copy to
- @type to_dt: L{ICUDateTime}
- """
- if not from_dt.isDateOnly():
- to_dt.setDateOnly(False)
- to_dt.setHHMMSS(from_dt.getHours(), from_dt.getMinutes(), from_dt.getSeconds())
- to_dt.setTimezoneID(from_dt.getTimezoneID())
- to_dt.setTimezoneUTC(from_dt.getTimezoneUTC())
-
-
- def convertTo(self, rscale):
- """
- Convert this L{ICUDateTime} into another one in the specified calendar scale.
-
- @param rscale: calendar scale to convert to
- @type rscale: L{str}
-
- @return: the converted date
- @rtype: L{ICUDateTime}
- """
- error = ffi.new("UErrorCode *", 0)
- converted = self._newUcal(rscale)
- millis = ICU.ucal_getMillis(self.ucal, error)
- ICU.ucal_setMillis(converted, millis, error)
- dt = ICUDateTime(rscale, converted)
- self._transferHHMMSS(self, dt)
-
- # For some reason this is needed to properly setup all the fields. Without this, I have
- # noticed that ucal_getLimit does not return the correct day of month limit for a Chinese
- # calendar.
- dt.getDateComponents()
-
- return dt
-
-
- def getDateComponents(self):
- """
- Get the year, month, day, isleapmonth components in our internal format from
- this ICU date.
-
- @return: the date components
- @rtype: L{tuple} of (L{int}, L{int}, L{int}, L{bool})
- """
- year = self.getYear()
- month = self.getMonth()
- day = self.getDay()
- isleapmonth = self.getLeapMonth()
-
- month, isleapmonth = self._adjustFromICULeapMonth(self.rscale, month, isleapmonth)
-
- return (year, month, day, isleapmonth,)
-
-
- def getPosixTime(self):
- """
- Return an integer representing a standard offset in seconds from a specific
- epoch. This is used for sorting similar object.
- """
-
- # Use the ICU "millis" for this.
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_getMillis(self.ucal, error)
-
-
- def isDateOnly(self):
- return self.mDateOnly
-
-
- def setDateOnly(self, date_only):
- self.mDateOnly = date_only
-
-
- def setYYMMDD(self, year, month, day, isleapmonth=False):
- self.setYear(year)
- self.setMonth(month, isleapmonth)
- self.setDay(day)
-
- self.testInvalid(year, month, day, isleapmonth)
-
-
- def getYear(self):
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_get(self.ucal, ICU.UCAL_EXTENDED_YEAR, error)
-
-
- def setYear(self, year):
- _ignore_old_year, old_month, old_day, old_isleapmonth = self.getDateComponents()
- ICU.ucal_set(self.ucal, ICU.UCAL_EXTENDED_YEAR, year)
- self.testInvalid(year, old_month, old_day, old_isleapmonth)
-
-
- def offsetYear(self, diff_year):
- """
- Offset the ICU date year component by the specified amount.
-
- @param diff_year: amount to offset
- @type diff_year: L{int}
- """
- error = ffi.new("UErrorCode *", 0)
- ICU.ucal_add(self.ucal, ICU.UCAL_EXTENDED_YEAR, diff_year, error)
-
-
- def getMonth(self):
- error = ffi.new("UErrorCode *", 0)
- return self._icuToNumericMonth(ICU.ucal_get(self.ucal, ICU.UCAL_MONTH, error))
-
-
- def setMonth(self, month, isleapmonth=False):
- old_year, _ignore_old_month, old_day, _ignore_old_isleapmonth = self.getDateComponents()
- ICU.ucal_set(self.ucal, ICU.UCAL_MONTH, self._numericMonthToICU(month))
- ICU.ucal_set(self.ucal, ICU.UCAL_IS_LEAP_MONTH, isleapmonth)
- self.testInvalid(old_year, month, old_day, isleapmonth)
-
-
- def offsetMonth(self, diff_month):
- """
- Offset the ICU date month component by the specified amount.
-
- @param diff_year: amount to offset
- @type diff_year: L{int}
- """
- error = ffi.new("UErrorCode *", 0)
- ICU.ucal_add(self.ucal, ICU.UCAL_MONTH, diff_month, error)
-
-
- def getLeapMonth(self):
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_get(self.ucal, ICU.UCAL_IS_LEAP_MONTH, error) != 0
-
-
- def getDay(self):
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_get(self.ucal, ICU.UCAL_DAY_OF_MONTH, error)
-
-
- def setDay(self, day):
- old_year, old_month, _ignore_old_day, old_isleapmonth = self.getDateComponents()
- ICU.ucal_set(self.ucal, ICU.UCAL_DAY_OF_MONTH, day)
- self.testInvalid(old_year, old_month, day, old_isleapmonth)
-
-
- def offsetDay(self, diff_day):
- """
- Offset the ICU date month component by the specified amount.
-
- @param diff_year: amount to offset
- @type diff_year: L{int}
- """
- error = ffi.new("UErrorCode *", 0)
- ICU.ucal_add(self.ucal, ICU.UCAL_DAY_OF_MONTH, diff_day, error)
-
-
- def setYearDay(self, day, allow_invalid=False):
-
- # Find the limit for the current year
- error = ffi.new("UErrorCode *", 0)
- limit = ICU.ucal_getLimit(self.ucal, ICU.UCAL_DAY_OF_YEAR, ICU.UCAL_ACTUAL_MAXIMUM, error)
-
- if day > 0:
- ICU.ucal_set(self.ucal, ICU.UCAL_DAY_OF_YEAR, min(day, limit))
- if day > limit and allow_invalid:
- self.setInvalid(self.getYear(), 1, day)
- else:
- self.clearInvalid()
- elif day < 0:
- offset = limit + day + 1
- ICU.ucal_set(self.ucal, ICU.UCAL_DAY_OF_YEAR, max(offset, 1))
- if offset <= 0 and allow_invalid:
- self.setInvalid(self.getYear(), 1, day)
- else:
- self.clearInvalid()
-
-
- def getYearDay(self):
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_get(self.ucal, ICU.UCAL_DAY_OF_YEAR, error)
-
-
- def setMonthDay(self, day, allow_invalid=False):
-
- # Find the limit for the current year
- error = ffi.new("UErrorCode *", 0)
- limit = ICU.ucal_getLimit(self.ucal, ICU.UCAL_DAY_OF_MONTH, ICU.UCAL_ACTUAL_MAXIMUM, error)
-
- if day > 0:
- ICU.ucal_set(self.ucal, ICU.UCAL_DAY_OF_MONTH, min(day, limit))
- if day > limit and allow_invalid:
- y, m, _ignore_d, l = self.getDateComponents()
- self.setInvalid(y, m, day, l)
- else:
- self.clearInvalid()
-
- elif day < 0:
- offset = limit + day + 1
- ICU.ucal_set(self.ucal, ICU.UCAL_DAY_OF_MONTH, max(offset, 1))
- if offset <= 0 and allow_invalid:
- y, m, _ignore_d, l = self.getDateComponents()
- self.setInvalid(y, m, day, l)
- else:
- self.clearInvalid()
-
-
- def isMonthDay(self, day):
- if day > 0:
- return self.getDay() == day
- elif day < 0:
- error = ffi.new("UErrorCode *", 0)
- limit = ICU.ucal_getLimit(self.ucal, ICU.UCAL_DAY_OF_MONTH, ICU.UCAL_ACTUAL_MAXIMUM, error)
- return self.getDay() - 1 - limit == day
- else:
- return False
-
-
- def setWeekNo(self, weekno):
- """
- 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.
-
- @param weekno: the week number to set (currently must be positive)
- @type weekno: C{int}
- """
-
- # Only supported for Gregorian calendars
- if self.rscale.lower() != self.RSCALE_GREGORIAN:
- raise ValueError("Week numbers only supported for Gregorian calendars")
- dt = self.toDateTime()
- dt.setWeekNo(weekno)
- self.setYYMMDD(dt.getYear(), dt.getMonth(), dt.getDay())
-
-
- def getWeekNo(self):
- """
- Return the ISO week number for the current date.
- """
-
- # Only supported for Gregorian calendars
- if self.rscale.lower() != self.RSCALE_GREGORIAN:
- raise ValueError("Week numbers only supported for Gregorian calendars")
- dt = self.toDateTime()
- return dt.getWeekNo()
-
-
- def isWeekNo(self, weekno):
- # This is the iso 8601 week number definition
-
- if weekno > 0:
- return self.getWeekNo() == weekno
- else:
- # This needs to calculate the negative offset from the last week in
- # the current year
- return False
-
-
- def setDayOfWeekInYear(self, offset, day):
- # Set to first day in year
- self.setYYMMDD(self.getYear(), 1, 1, False)
-
- # Determine first weekday in year
- first_day = self.getDayOfWeek()
-
- if offset > 0:
- cycle = (offset - 1) * 7 + day
- cycle -= first_day
- if first_day > day:
- cycle += 7
- self.offsetDay(cycle)
- elif offset < 0:
- # Find the limit for the current year
- error = ffi.new("UErrorCode *", 0)
- limit = ICU.ucal_getLimit(self.ucal, ICU.UCAL_DAY_OF_YEAR, ICU.UCAL_ACTUAL_MAXIMUM, error)
-
- first_day += limit - 1
- first_day %= 7
-
- cycle = (-offset - 1) * 7 - day
- cycle += first_day
- if day > first_day:
- cycle += 7
- self.offsetDay(limit - cycle - 1)
-
- self.clearInvalid()
-
-
- def setDayOfWeekInMonth(self, offset, day, allow_invalid=False):
- # Set to first day in month
- y, m, d, l = self.getDateComponents()
- self.setYYMMDD(y, m, 1, l)
-
- # Determine first weekday in month
- first_day = self.getDayOfWeek()
-
- if offset > 0:
- cycle = (offset - 1) * 7 + day
- cycle -= first_day
- if first_day > day:
- cycle += 7
- mday = cycle + 1
- self.offsetDay(cycle)
- elif offset < 0:
- # Find the limit for the current year
- error = ffi.new("UErrorCode *", 0)
- days_in_month = ICU.ucal_getLimit(self.ucal, ICU.UCAL_DAY_OF_MONTH, ICU.UCAL_ACTUAL_MAXIMUM, error)
-
- first_day += days_in_month - 1
- first_day %= 7
-
- cycle = (-offset - 1) * 7 - day
- cycle += first_day
- if day > first_day:
- cycle += 7
- mday = days_in_month - cycle
- self.offsetDay(days_in_month - cycle - 1)
-
- if self.getDay() != mday and allow_invalid:
- self.setInvalid(y, m, d, l)
- else:
- self.clearInvalid()
-
-
- def isDayOfWeekInMonth(self, offset, day):
- # First of the actual day must match
- if self.getDayOfWeek() != day:
- return False
-
- # If there is no count the we match any of this day in the month
- if offset == 0:
- return True
-
- # Create temp date-time with the appropriate parameters and then
- # compare
- temp = self.duplicate()
- temp.setDayOfWeekInMonth(offset, day)
-
- # Now compare dates
- return self.getDateComponents() == temp.getDateComponents()
-
-
- def getDayOfWeek(self):
- error = ffi.new("UErrorCode *", 0)
- return ICU.ucal_get(self.ucal, ICU.UCAL_DAY_OF_WEEK, error) - 1
-
-
- def setHHMMSS(self, hours, minutes, seconds):
- if (self.mHours != hours) or (self.mMinutes != minutes) or (self.mSeconds != seconds):
- self.mHours = hours
- self.mMinutes = minutes
- self.mSeconds = seconds
-
-
- def getHours(self):
- return self.mHours
-
-
- def setHours(self, hours):
- if self.mHours != hours:
- self.mHours = hours
-
-
- def offsetHours(self, diff_hour):
- self.mHours += diff_hour
- self.normalise()
-
-
- def getMinutes(self):
- return self.mMinutes
-
-
- def setMinutes(self, minutes):
- if self.mMinutes != minutes:
- self.mMinutes = minutes
-
-
- def offsetMinutes(self, diff_minutes):
- self.mMinutes += diff_minutes
- self.normalise()
-
-
- def getSeconds(self):
- return self.mSeconds
-
-
- def setSeconds(self, seconds):
- if self.mSeconds != seconds:
- self.mSeconds = seconds
-
-
- def offsetSeconds(self, diff_seconds):
- self.mSeconds += diff_seconds
- self.normalise()
-
-
- def getTimezoneUTC(self):
- return self.mTZUTC
-
-
- def setTimezoneUTC(self, utc):
- if self.mTZUTC != utc:
- self.mTZUTC = utc
-
-
- def getTimezoneID(self):
- return self.mTZID
-
-
- def setTimezoneID(self, tzid):
- self.mTZUTC = False
- self.mTZID = tzid
-
-
- # When doing recurrence iteration we sometimes need to preserve an invalid value for
- # either day or month (though month is never invalid for Gregorian calendars it can
- # be for non-Gregorian). For this class we simply set the stored attributes to their
- # invalid values.
- def setInvalid(self, year, month, day, isleapmonth=False):
- self.mInvalid = (year, month, day, isleapmonth,)
-
-
- def testInvalid(self, year, month, day, isleapmonth=False):
- """
- If the requested set of YYMMDDLL does not match the current set of YYMMDDLL then the requested
- set was invalid.
- """
- components = self.getDateComponents()
- if components != (year, month, day, isleapmonth,):
- self.setInvalid(year, month, day, isleapmonth)
- else:
- self.clearInvalid()
-
-
- def clearInvalid(self):
- self.mInvalid = None
-
-
- def invalid(self):
- """
- Are any of the current fields invalid.
- """
-
- # Right now we only care about invalid days of the month (e.g. February 30th). In the
- # future we may also want to look for invalid times during a DST transition.
-
- return self.mInvalid is not None
-
-
- def invalidSkip(self, skip):
- """
- If this is an invalid value skip backward or forward or not at all.
-
- @param skip: the skip mode (yes, backward, forward)
- @type skip: L{int}
- """
-
- if self.mInvalid:
- if skip == definitions.eRecurrence_SKIP_YES:
- # Leave it as invalid
- pass
- else:
- # Need to determine which component (day or month/leap) is invalid,
- # and react accordingly
- _ignore_y, m, d, l = self.getDateComponents()
- if (m, l) != (self.mInvalid[1], self.mInvalid[3]):
- # Month/leap is invalid
- if skip == definitions.eRecurrence_SKIP_BACKWARD:
- # Defaults to skip backward
- pass
- elif skip == definitions.eRecurrence_SKIP_FORWARD:
- self.offsetDay(1)
-
- elif d != self.mInvalid[2]:
- if skip == definitions.eRecurrence_SKIP_BACKWARD:
- if self.mInvalid[2] < 1:
- self.offsetDay(-1)
- elif skip == definitions.eRecurrence_SKIP_FORWARD:
- if self.mInvalid[2] > 0:
- self.offsetDay(1)
-
- self.clearInvalid()
-
-
- def normalise(self):
- # Normalise seconds
- normalised_secs = self.mSeconds % 60
- adjustment_mins = self.mSeconds / 60
- if normalised_secs < 0:
- normalised_secs += 60
- adjustment_mins -= 1
- self.mSeconds = normalised_secs
- self.mMinutes += adjustment_mins
-
- # Normalise minutes
- normalised_mins = self.mMinutes % 60
- adjustment_hours = self.mMinutes / 60
- if normalised_mins < 0:
- normalised_mins += 60
- adjustment_hours -= 1
- self.mMinutes = normalised_mins
- self.mHours += adjustment_hours
-
- # Normalise hours
- normalised_hours = self.mHours % 24
- adjustment_days = self.mHours / 24
- if normalised_hours < 0:
- normalised_hours += 24
- adjustment_days -= 1
- self.mHours = normalised_hours
-
- self.offsetDay(adjustment_days)
-
- # Wipe the time if date only
- if self.mDateOnly:
- self.mSeconds = self.mMinutes = self.mHours = 0
-
-
- def getText(self):
- """
- Generate an ISO-8601 string representation of this ICU date. Use a code
- prefix for the calendar scale.
-
- @return: the ISO-8601 text
- @rtype L{str}
- """
- calcode = self.RSCALE_CALCODE.get(self.rscale.lower(), "{}:".format(self.rscale))
- if calcode:
- calcode = "{{{}}}".format(calcode)
- year, month, day, isleapmonth = self.getDateComponents()
- date = "{}{:04d}{:02d}{}{:02d}".format(calcode, year, month, "L" if isleapmonth else "", day)
- if not self.isDateOnly():
- date += "T{:02d}{:02d}{:02d}{}".format(self.mHours, self.mMinutes, self.mSeconds, "Z" if self.mTZUTC else "")
- return date
-
-
-if __name__ == '__main__':
- newyear = ICUDateTime.fromDateComponents("chinese", 4651, 1, 1, False)
- print("From: {} to {}".format(
- newyear.getText(),
- newyear.convertTo("gregorian").getText(),
- ))
-
- for i in range(0):
- newyear.offsetDay(1)
- print("From: {} to {}".format(
- newyear.getText(),
- newyear.convertTo("gregorian").getText(),
- ))
-
- offset = 1
- greg = ICUDateTime.fromDateComponents("gregorian", 2014, 1, 31, False)
- greg.offsetMonth(offset)
- print(greg.getText())
-
- greg = DateTime(2014, 1, 31)
- greg.offsetMonth(offset)
- print(greg.getText())
</del></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarrecuriterpy"></a>
<div class="delfile"><h4>Deleted: PyCalendar/trunk/src/pycalendar/icalendar/recuriter.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/recuriter.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/recuriter.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -1,151 +0,0 @@
</span><del>-##
-# Copyright (c) 2014 Cyrus Daboo. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from pycalendar.icalendar import definitions
-from pycalendar.icalendar.icudatetime import ICUDateTime
-import collections
-
-class RecurrenceIterator(collections.Iterator):
- """
- An iterator that iterates a simple recurrence pattern.
- """
-
- def __init__(self, start, freq, interval, rscale=None, skip=definitions.eRecurrence_SKIP_YES, allow_invalid=False):
- """
- @param start: the start date-time
- @type start: L{DateTime} or L{ICUDateTime}
- @param freq: the frequency of iteration
- @type freq: L{int}
- @param interval: the interval for each iteration
- @type interval: L{int}
- @param rscale: calendar scale to apply recurrence pattern to
- @type rscale: L{str}
- @param skip: skipping behavior for invalid dates
- @type skip: L{int}
- @param allow_invalid: whether or not invalid values are allowed
- @type allow_invalid: L{InvalidDateTime}
- """
- self.start = start
- self.freq = freq
- self.interval = interval
- self.rscale = rscale
- self.skip = skip
- self.allow_invalid = allow_invalid
-
- self.step = 0
-
- # If an RSCALE is set, the C{self.start} value is a normal L{DateTime} object but we want
- # to have the recurrence apply to the non-Gregorian calendar. So convert the C{self.start}
- # value into the corresponding L{ICUDateTime} object.
- if self.rscale:
- self.start = ICUDateTime.fromDateTime(self.start, self.rscale)
-
-
- def __iter__(self):
- return self
-
-
- def next(self):
- """
- Iterate one step of the recurrence. Always return an L{DateTime} for an rscale based
- recurrence.
-
- @return: the resulting date-time - this object is not re-used by the iterator so can be used
- directly by the caller without any need to copy it
- @rtype L{DateTime}
- """
-
- dt = self.nextraw()
-
- # Always return the L{DateTime} equivalent when using C{self.rscale}
- return dt.toDateTime() if self.rscale else dt
-
-
- def nextraw(self):
- """
- Iterate one step of the recurrence using the native date-time calendar scale, and return
- the native value.
-
- @return: the resulting date-time - this object is not re-used by the iterator so can be used
- directly by the caller without any need to copy it
- @rtype L{DateTime} or L{ICUDateTime}
- """
-
- dt = self.start.duplicate()
-
- # Add appropriate interval
- if self.freq == definitions.eRecurrence_SECONDLY:
- dt.offsetSeconds(self.step)
- elif self.freq == definitions.eRecurrence_MINUTELY:
- dt.offsetMinutes(self.step)
- elif self.freq == definitions.eRecurrence_HOURLY:
- dt.offsetHours(self.step)
- elif self.freq == definitions.eRecurrence_DAILY:
- dt.offsetDay(self.step)
- elif self.freq == definitions.eRecurrence_WEEKLY:
- dt.offsetDay(7 * self.step)
- elif self.freq == definitions.eRecurrence_MONTHLY:
- dt.offsetMonth(self.step)
-
- # Check whether the day matches the start - if not we stepped
- # to an invalid date so apply skip behavior
- if dt.getDay() != self.start.getDay():
- if self.allow_invalid:
- dt.setInvalid(dt.getYear(), dt.getMonth(), self.start.getDay(), dt.getLeapMonth())
- elif self.skip == definitions.eRecurrence_SKIP_YES:
- # Iterate until we have a valid month
- while dt.getDay() != self.start.getDay():
- self.step += self.interval
- dt = self.start.duplicate()
- dt.offsetMonth(self.step)
- elif self.skip == definitions.eRecurrence_SKIP_BACKWARD:
- # Both ICU and PyCalendar skip back by default
- pass
- elif self.skip == definitions.eRecurrence_SKIP_FORWARD:
- # Go one day forward
- dt.offsetDay(1)
-
- elif self.freq == definitions.eRecurrence_YEARLY:
- dt.offsetYear(self.step)
-
- # Check whether the month/day matches the start - if not we stepped
- # to an invalid date so apply skip behavior
- if dt.getDay() != self.start.getDay() or dt.getMonth() != self.start.getMonth() or dt.getLeapMonth() != self.start.getLeapMonth():
- if self.allow_invalid:
- dt.setInvalid(dt.getYear(), self.start.getMonth(), self.start.getDay(), self.start.getLeapMonth())
- elif self.skip == definitions.eRecurrence_SKIP_YES:
- # Iterate until we have a valid date-time
- while dt.getDay() != self.start.getDay() or dt.getMonth() != self.start.getMonth() or dt.getLeapMonth() != self.start.getLeapMonth():
- self.step += self.interval
- dt = self.start.duplicate()
- dt.offsetYear(self.step)
- elif self.skip == definitions.eRecurrence_SKIP_BACKWARD:
- # Both ICU and PyCalendar skip back by default
- pass
- elif self.skip == definitions.eRecurrence_SKIP_FORWARD:
- # Go one day forward
- dt.offsetDay(1)
-
- self.step += self.interval
-
- return dt
-
-
-if __name__ == '__main__':
- icudt = ICUDateTime.fromDateComponents("gregorian", 2014, 1, 31)
- iter = RecurrenceIterator(icudt, definitions.eRecurrence_MONTHLY, 1, definitions.eRecurrence_SKIP_BACKWARD)
- for i in range(12):
- print(iter.next().getText())
</del></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarrecurrencepy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/icalendar/recurrence.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/recurrence.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/recurrence.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -21,7 +21,6 @@
</span><span class="cx"> from pycalendar.valueutils import ValueMixin
</span><span class="cx"> import cStringIO as StringIO
</span><span class="cx"> import xml.etree.cElementTree as XML
</span><del>-from pycalendar.icalendar.recuriter import RecurrenceIterator
</del><span class="cx">
</span><span class="cx"> def WeekDayNumCompare_compare(w1, w2):
</span><span class="cx">
</span><span class="lines">@@ -56,8 +55,6 @@
</span><span class="cx"> definitions.cICalValue_RECUR_YEARLY : definitions.eRecurrence_YEARLY,
</span><span class="cx"> }
</span><span class="cx">
</span><del>- cFreqInverseMap = dict([(v, k) for k, v in cFreqMap.items()])
-
</del><span class="cx"> cFreqToXMLMap = {
</span><span class="cx"> definitions.eRecurrence_SECONDLY: xmldefinitions.recur_freq_secondly,
</span><span class="cx"> definitions.eRecurrence_MINUTELY: xmldefinitions.recur_freq_minutely,
</span><span class="lines">@@ -83,8 +80,6 @@
</span><span class="cx"> definitions.cICalValue_RECUR_BYMONTH : definitions.eRecurrence_BYMONTH,
</span><span class="cx"> definitions.cICalValue_RECUR_BYSETPOS : definitions.eRecurrence_BYSETPOS,
</span><span class="cx"> definitions.cICalValue_RECUR_WKST : definitions.eRecurrence_WKST,
</span><del>- definitions.cICalValue_RECUR_RSCALE : definitions.eRecurrence_RSCALE,
- definitions.cICalValue_RECUR_SKIP : definitions.eRecurrence_SKIP,
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> cWeekdayMap = {
</span><span class="lines">@@ -99,20 +94,6 @@
</span><span class="cx">
</span><span class="cx"> cWeekdayRecurMap = dict([(v, k) for k, v in cWeekdayMap.items()])
</span><span class="cx">
</span><del>- cSkipMap = {
- definitions.cICalValue_RECUR_SKIP_YES : definitions.eRecurrence_SKIP_YES,
- definitions.cICalValue_RECUR_SKIP_BACKWARD : definitions.eRecurrence_SKIP_BACKWARD,
- definitions.cICalValue_RECUR_SKIP_FORWARD : definitions.eRecurrence_SKIP_FORWARD,
- }
-
- cSkipInverseMap = dict([(v, k) for k, v in cSkipMap.items()])
-
- cSkipToXMLMap = {
- definitions.eRecurrence_SKIP_YES: xmldefinitions.recur_skip_yes,
- definitions.eRecurrence_SKIP_BACKWARD: xmldefinitions.recur_skip_backward,
- definitions.eRecurrence_SKIP_FORWARD: xmldefinitions.recur_skip_forward,
- }
-
</del><span class="cx"> cUnknownIndex = -1
</span><span class="cx">
</span><span class="cx"> def __init__(self):
</span><span class="lines">@@ -122,7 +103,6 @@
</span><span class="cx"> def duplicate(self):
</span><span class="cx"> other = Recurrence()
</span><span class="cx">
</span><del>- other.mRscale = self.mRscale
</del><span class="cx"> other.mFreq = self.mFreq
</span><span class="cx">
</span><span class="cx"> other.mUseCount = self.mUseCount
</span><span class="lines">@@ -132,9 +112,6 @@
</span><span class="cx"> other.mUntil = self.mUntil.duplicate()
</span><span class="cx">
</span><span class="cx"> other.mInterval = self.mInterval
</span><del>-
- other.mSkip = self.mSkip
-
</del><span class="cx"> if self.mBySeconds is not None:
</span><span class="cx"> other.mBySeconds = self.mBySeconds[:]
</span><span class="cx"> if self.mByMinutes is not None:
</span><span class="lines">@@ -168,8 +145,6 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def init_Recurrence(self):
</span><del>-
- self.mRscale = None
</del><span class="cx"> self.mFreq = definitions.eRecurrence_YEARLY
</span><span class="cx">
</span><span class="cx"> self.mUseCount = False
</span><span class="lines">@@ -179,9 +154,6 @@
</span><span class="cx"> self.mUntil = None
</span><span class="cx">
</span><span class="cx"> self.mInterval = 1
</span><del>-
- self.mSkip = None
-
</del><span class="cx"> self.mBySeconds = None
</span><span class="cx"> self.mByMinutes = None
</span><span class="cx"> self.mByHours = None
</span><span class="lines">@@ -202,14 +174,12 @@
</span><span class="cx">
</span><span class="cx"> def __hash__(self):
</span><span class="cx"> return hash((
</span><del>- self.mRscale,
</del><span class="cx"> self.mFreq,
</span><span class="cx"> self.mUseCount,
</span><span class="cx"> self.mCount,
</span><span class="cx"> self.mUseUntil,
</span><span class="cx"> self.mUntil,
</span><span class="cx"> self.mInterval,
</span><del>- self.mSkip,
</del><span class="cx"> tuple(self.mBySeconds) if self.mBySeconds else None,
</span><span class="cx"> tuple(self.mByMinutes) if self.mByMinutes else None,
</span><span class="cx"> tuple(self.mByHours) if self.mByHours else None,
</span><span class="lines">@@ -235,12 +205,10 @@
</span><span class="cx">
</span><span class="cx"> def equals(self, comp):
</span><span class="cx"> return (
</span><del>- (self.mRscale == comp.mRscale)
- and (self.mFreq == comp.mFreq)
</del><ins>+ (self.mFreq == comp.mFreq)
</ins><span class="cx"> and (self.mUseCount == comp.mUseCount) and (self.mCount == comp.mCount)
</span><span class="cx"> and (self.mUseUntil == comp.mUseUntil) and (self.mUntil == comp.mUntil)
</span><span class="cx"> and (self.mInterval == comp.mInterval)
</span><del>- and (self.mSkip == comp.mSkip)
</del><span class="cx"> and self.equalsNum(self.mBySeconds, comp.mBySeconds)
</span><span class="cx"> and self.equalsNum(self.mByMinutes, comp.mByMinutes)
</span><span class="cx"> and self.equalsNum(self.mByHours, comp.mByHours)
</span><span class="lines">@@ -306,14 +274,6 @@
</span><span class="cx"> setattr(self, attr, value)
</span><span class="cx">
</span><span class="cx">
</span><del>- def getRscale(self):
- return self.mRscale
-
-
- def setRscale(self, rscale):
- self._setAndclearIfChanged("mRscale", rscale)
-
-
</del><span class="cx"> def getFreq(self):
</span><span class="cx"> return self.mFreq
</span><span class="cx">
</span><span class="lines">@@ -362,24 +322,6 @@
</span><span class="cx"> self._setAndclearIfChanged("mInterval", interval)
</span><span class="cx">
</span><span class="cx">
</span><del>- def getSkip(self):
- return self.mSkip
-
-
- def effectiveSkip(self):
- """
- The default skip value depends on whether RSCALE is used or not
- """
- if self.mSkip is None:
- return definitions.eRecurrence_SKIP_YES if self.mRscale is None else definitions.eRecurrence_SKIP_BACKWARD
- else:
- return self.mSkip
-
-
- def setSkip(self, skip):
- self._setAndclearIfChanged("mSkip", skip)
-
-
</del><span class="cx"> def getByMonth(self):
</span><span class="cx"> return self.mByMonth
</span><span class="cx">
</span><span class="lines">@@ -531,7 +473,7 @@
</span><span class="cx"> if self.mByMonth is not None:
</span><span class="cx"> raise ValueError("Recurrence: Only one BYMONTH allowed")
</span><span class="cx"> self.mByMonth = []
</span><del>- self.parseMonthNumList(tvalue, self.mByMonth, 1, 12, errmsg="Recurrence: Invalid BYMONTH value")
</del><ins>+ self.parseList(tvalue, self.mByMonth, 1, 12, errmsg="Recurrence: Invalid BYMONTH value")
</ins><span class="cx">
</span><span class="cx"> elif index == definitions.eRecurrence_BYSETPOS:
</span><span class="cx"> if self.mBySetPos is not None:
</span><span class="lines">@@ -545,21 +487,7 @@
</span><span class="cx"> raise ValueError("Recurrence: Invalid WKST value")
</span><span class="cx"> self.mWeekstart = index
</span><span class="cx">
</span><del>- elif index == definitions.eRecurrence_RSCALE:
- self.mRscale = tvalue.upper()
</del><span class="cx">
</span><del>- elif index == definitions.eRecurrence_SKIP:
- # Get the SKIP value
- index = Recurrence.cSkipMap.get(tvalue, Recurrence.cUnknownIndex)
- if index == Recurrence.cUnknownIndex:
- raise ValueError("Recurrence: Invalid SKIP value")
- self.mSkip = index
-
- # Final validity checks
- if self.mRscale is None and self.mSkip is not None:
- raise ValueError("Recurrence: SKIP only allowed with RSCALE")
-
-
</del><span class="cx"> def parseList(self, txt, list, min=None, max=None, allowNegative=False, errmsg=""):
</span><span class="cx">
</span><span class="cx"> if "," in txt:
</span><span class="lines">@@ -579,33 +507,6 @@
</span><span class="cx"> list.append(value)
</span><span class="cx">
</span><span class="cx">
</span><del>- def parseMonthNumList(self, txt, list, min=None, max=None, allowNegative=False, errmsg=""):
- """
- Month numbers can include "L" leap month suffix.
- """
-
- if "," in txt:
- tokens = txt.split(",")
- else:
- tokens = (txt,)
-
- for token in tokens:
- if token.endswith("L"):
- suffix = True
- token = token[:-1]
- else:
- suffix = False
- value = int(token)
- if not allowNegative and value < 0:
- raise ValueError(errmsg)
- avalue = abs(value)
- if min is not None and avalue < min:
- raise ValueError(errmsg)
- if max is not None and avalue > max:
- raise ValueError(errmsg)
- list.append((value, suffix,))
-
-
</del><span class="cx"> def parseListDW(self, txt, list, errmsg=""):
</span><span class="cx">
</span><span class="cx"> if "," in txt:
</span><span class="lines">@@ -641,16 +542,30 @@
</span><span class="cx">
</span><span class="cx"> def generate(self, os):
</span><span class="cx"> try:
</span><del>- if self.mRscale:
- os.write(definitions.cICalValue_RECUR_RSCALE)
- os.write("=")
- os.write(self.mRscale.upper())
- os.write(";")
-
</del><span class="cx"> os.write(definitions.cICalValue_RECUR_FREQ)
</span><span class="cx"> os.write("=")
</span><del>- os.write(self.cFreqInverseMap[self.mFreq])
</del><span class="cx">
</span><ins>+ if self.mFreq == definitions.eRecurrence_SECONDLY:
+ os.write(definitions.cICalValue_RECUR_SECONDLY)
+
+ elif self.mFreq == definitions.eRecurrence_MINUTELY:
+ os.write(definitions.cICalValue_RECUR_MINUTELY)
+
+ elif self.mFreq == definitions.eRecurrence_HOURLY:
+ os.write(definitions.cICalValue_RECUR_HOURLY)
+
+ elif self.mFreq == definitions.eRecurrence_DAILY:
+ os.write(definitions.cICalValue_RECUR_DAILY)
+
+ elif self.mFreq == definitions.eRecurrence_WEEKLY:
+ os.write(definitions.cICalValue_RECUR_WEEKLY)
+
+ elif self.mFreq == definitions.eRecurrence_MONTHLY:
+ os.write(definitions.cICalValue_RECUR_MONTHLY)
+
+ elif self.mFreq == definitions.eRecurrence_YEARLY:
+ os.write(definitions.cICalValue_RECUR_YEARLY)
+
</ins><span class="cx"> if self.mUseCount:
</span><span class="cx"> os.write(";")
</span><span class="cx"> os.write(definitions.cICalValue_RECUR_COUNT)
</span><span class="lines">@@ -668,12 +583,6 @@
</span><span class="cx"> os.write("=")
</span><span class="cx"> os.write(str(self.mInterval))
</span><span class="cx">
</span><del>- if self.mSkip is not None:
- os.write(";")
- os.write(definitions.cICalValue_RECUR_SKIP)
- os.write("=")
- os.write(self.cSkipInverseMap[self.mSkip])
-
</del><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYSECOND, self.mBySeconds)
</span><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYMINUTE, self.mByMinutes)
</span><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYHOUR, self.mByHours)
</span><span class="lines">@@ -715,7 +624,7 @@
</span><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYMONTHDAY, self.mByMonthDay)
</span><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYYEARDAY, self.mByYearDay)
</span><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYWEEKNO, self.mByWeekNo)
</span><del>- self.generateMonthNumList(os, definitions.cICalValue_RECUR_BYMONTH, self.mByMonth)
</del><ins>+ self.generateList(os, definitions.cICalValue_RECUR_BYMONTH, self.mByMonth)
</ins><span class="cx"> self.generateList(os, definitions.cICalValue_RECUR_BYSETPOS, self.mBySetPos)
</span><span class="cx">
</span><span class="cx"> # MO is the default so we do not need it
</span><span class="lines">@@ -763,31 +672,10 @@
</span><span class="cx"> os.write(str(e))
</span><span class="cx">
</span><span class="cx">
</span><del>- def generateMonthNumList(self, os, title, items):
- """
- Month numbers can include "L" leap month suffix.
- """
-
- if (items is not None) and (len(items) != 0):
- os.write(";")
- os.write(title)
- os.write("=")
- comma = False
- for item in items:
- if comma:
- os.write(",")
- comma = True
- os.write(str(item[0]) + ("L" if item[1] else ""))
-
-
</del><span class="cx"> def writeXML(self, node, namespace):
</span><span class="cx">
</span><span class="cx"> recur = XML.SubElement(node, xmlutils.makeTag(namespace, xmldefinitions.value_recur))
</span><span class="cx">
</span><del>- if self.mRscale:
- freq = XML.SubElement(recur, xmlutils.makeTag(namespace, xmldefinitions.recur_rscale))
- freq.text = self.mRscale
-
</del><span class="cx"> freq = XML.SubElement(recur, xmlutils.makeTag(namespace, xmldefinitions.recur_freq))
</span><span class="cx"> freq.text = self.cFreqToXMLMap[self.mFreq]
</span><span class="cx">
</span><span class="lines">@@ -802,10 +690,6 @@
</span><span class="cx"> interval = XML.SubElement(recur, xmlutils.makeTag(namespace, xmldefinitions.recur_interval))
</span><span class="cx"> interval.text = str(self.mInterval)
</span><span class="cx">
</span><del>- if self.mSkip is not None:
- skip = XML.SubElement(recur, xmlutils.makeTag(namespace, xmldefinitions.recur_skip))
- skip.text = self.cSkipToXMLMap[self.mSkip]
-
</del><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_bysecond, self.mBySeconds)
</span><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_byminute, self.mByMinutes)
</span><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_byhour, self.mByHours)
</span><span class="lines">@@ -822,7 +706,7 @@
</span><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_bymonthday, self.mByMonthDay)
</span><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_byyearday, self.mByYearDay)
</span><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_byweekno, self.mByWeekNo)
</span><del>- self.writeXMLMonthNumList(recur, namespace, xmldefinitions.recur_bymonth, self.mByMonth)
</del><ins>+ self.writeXMLList(recur, namespace, xmldefinitions.recur_bymonth, self.mByMonth)
</ins><span class="cx"> self.writeXMLList(recur, namespace, xmldefinitions.recur_bysetpos, self.mBySetPos)
</span><span class="cx">
</span><span class="cx"> # MO is the default so we do not need it
</span><span class="lines">@@ -838,17 +722,6 @@
</span><span class="cx"> child.text = str(item)
</span><span class="cx">
</span><span class="cx">
</span><del>- def writeXMLMonthNumList(self, node, namespace, name, items):
- """
- Month numbers can include "L" leap month suffix.
- """
-
- if items is not None and len(items) != 0:
- for item in items:
- child = XML.SubElement(node, xmlutils.makeTag(namespace, name))
- child.text = str(item[0]) + ("L" if item[1] else "")
-
-
</del><span class="cx"> def parseJSON(self, jobject):
</span><span class="cx"> """
</span><span class="cx"> jCal splits the value into components. We need to convert that back to the
</span><span class="lines">@@ -877,9 +750,6 @@
</span><span class="cx"> """
</span><span class="cx"> jdict = {}
</span><span class="cx">
</span><del>- if self.mRscale:
- jdict[xmldefinitions.recur_rscale] = self.mRscale
-
</del><span class="cx"> jdict[xmldefinitions.recur_freq] = self.cFreqToXMLMap[self.mFreq]
</span><span class="cx">
</span><span class="cx"> if self.mUseCount:
</span><span class="lines">@@ -890,9 +760,6 @@
</span><span class="cx"> if self.mInterval > 1:
</span><span class="cx"> jdict[xmldefinitions.recur_interval] = self.mInterval
</span><span class="cx">
</span><del>- if self.mSkip is not None:
- jdict[xmldefinitions.recur_skip] = self.cSkipToXMLMap[self.mSkip]
-
</del><span class="cx"> if self.mBySeconds:
</span><span class="cx"> jdict[xmldefinitions.recur_bysecond] = self.mBySeconds
</span><span class="cx"> if self.mByMinutes:
</span><span class="lines">@@ -917,7 +784,7 @@
</span><span class="cx"> if self.mByWeekNo:
</span><span class="cx"> jdict[xmldefinitions.recur_byweekno] = self.mByWeekNo
</span><span class="cx"> if self.mByMonth:
</span><del>- jdict[xmldefinitions.recur_bymonth] = [(str(item[0]) + "L") if item[1] else item[0] for item in self.mByMonth]
</del><ins>+ jdict[xmldefinitions.recur_bymonth] = self.mByMonth
</ins><span class="cx"> if self.mBySetPos:
</span><span class="cx"> jdict[xmldefinitions.recur_bysetpos] = self.mBySetPos
</span><span class="cx">
</span><span class="lines">@@ -1058,7 +925,9 @@
</span><span class="cx"> return limited
</span><span class="cx">
</span><span class="cx">
</span><del>- def simpleExpand(self, start, range, results, float_offset):
</del><ins>+ def simpleExpand(self, start, range, items, float_offset):
+ start_iter = start.duplicate()
+ ctr = 0
</ins><span class="cx">
</span><span class="cx"> if self.mUseUntil:
</span><span class="cx"> float_until = self.mUntil.duplicate()
</span><span class="lines">@@ -1066,30 +935,35 @@
</span><span class="cx"> float_until.setTimezoneID(0)
</span><span class="cx"> float_until.offsetSeconds(float_offset)
</span><span class="cx">
</span><del>- riter = RecurrenceIterator(start, self.mFreq, self.mInterval, self.mRscale, self.effectiveSkip())
</del><span class="cx"> while True:
</span><del>- start_iter = riter.next()
-
</del><span class="cx"> # Exit if after period we want
</span><span class="cx"> if range.isDateAfterPeriod(start_iter):
</span><span class="cx"> return False
</span><del>- elif self.mUseUntil:
- # Exit if next item is after until (it is OK if it is the same as
- # UNTIL as UNTIL is inclusive)
- if start_iter > float_until:
- return True
</del><span class="cx">
</span><span class="cx"> # Add current one to list
</span><del>- results.append(start_iter)
</del><ins>+ items.append(start_iter.duplicate())
</ins><span class="cx">
</span><ins>+ # Get next item
+ start_iter.recur(self.mFreq, self.mInterval, allow_invalid=True)
+ while start_iter.invalid():
+ start_iter.recur(self.mFreq, self.mInterval, allow_invalid=True)
+
</ins><span class="cx"> # Check limits
</span><span class="cx"> if self.mUseCount:
</span><del>- # Exit if max count reached
- if len(results) >= self.mCount:
</del><ins>+ # Bump counter and exit if over
+ ctr += 1
+ if ctr >= self.mCount:
</ins><span class="cx"> return True
</span><ins>+ elif self.mUseUntil:
+ # Exit if next item is after until (its OK if its the same as
+ # UNTIL as UNTIL is inclusive)
+ if start_iter > float_until:
+ return True
</ins><span class="cx">
</span><span class="cx">
</span><del>- def complexExpand(self, start, range, results, float_offset):
</del><ins>+ def complexExpand(self, start, range, items, float_offset):
+ start_iter = start.duplicate()
+ ctr = 0
</ins><span class="cx">
</span><span class="cx"> if self.mUseUntil:
</span><span class="cx"> float_until = self.mUntil.duplicate()
</span><span class="lines">@@ -1097,15 +971,16 @@
</span><span class="cx"> float_until.setTimezoneID(None)
</span><span class="cx"> float_until.offsetSeconds(float_offset)
</span><span class="cx">
</span><del>- # Allow invalid values during the complex iteration as those may end up being coerced to a valid value
- # when a BYxxx rule expands
- riter = RecurrenceIterator(start, self.mFreq, self.mInterval, self.mRscale, self.effectiveSkip(), allow_invalid=True)
- while True:
- # Keep the iterated date-time value in its native calendar scale
- start_iter = riter.nextraw()
</del><ins>+ # Always add the initial instance DTSTART
+ if self.mUseCount:
+ # Bump counter and exit if over
+ ctr += 1
+ if ctr >= self.mCount:
+ return True
</ins><span class="cx">
</span><del>- # Each recurrence cycle may generate multiple items based on the frequency and other rule parts,
- # but we need to limit based on until and range and count
</del><ins>+ # Need to re-initialise start based on BYxxx rules
+ while True:
+ # Behaviour is based on frequency
</ins><span class="cx"> set_items = []
</span><span class="cx">
</span><span class="cx"> if self.mFreq == definitions.eRecurrence_SECONDLY:
</span><span class="lines">@@ -1130,23 +1005,12 @@
</span><span class="cx"> self.generateYearlySet(start_iter, set_items)
</span><span class="cx">
</span><span class="cx"> # Ignore if it is invalid
</span><del>- def _invalidMap(dt):
- dt.invalidSkip(self.effectiveSkip())
- return dt
- set_items = map(lambda x: _invalidMap(x), set_items)
</del><span class="cx"> set_items = filter(lambda x: not x.invalid(), set_items)
</span><span class="cx">
</span><span class="cx"> # Always sort the set as BYxxx rules may not be sorted
</span><span class="cx"> # set_items.sort(cmp=DateTime.sort)
</span><span class="cx"> set_items.sort(key=lambda x: x.getPosixTime())
</span><span class="cx">
</span><del>- if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
- set_items[:] = self.bySetPosLimit(set_items)
-
- # Remaining behavior requires L{DateTime} objects
- if self.mRscale:
- set_items[:] = map(lambda date: date.toDateTime(), set_items)
-
</del><span class="cx"> # Process each one in the generated set
</span><span class="cx"> for iter in set_items:
</span><span class="cx">
</span><span class="lines">@@ -1163,22 +1027,34 @@
</span><span class="cx"> return False
</span><span class="cx">
</span><span class="cx"> # Exit if beyond the UNTIL limit
</span><del>- elif self.mUseUntil:
</del><ins>+ if self.mUseUntil:
</ins><span class="cx"> # Exit if next item is after until (its OK if its the same
</span><span class="cx"> # as UNTIL as UNTIL is inclusive)
</span><span class="cx"> if iter > float_until:
</span><span class="cx"> return True
</span><span class="cx">
</span><ins>+ # Special for start instance
+ if (ctr == 1) and (start == iter):
+ continue
+
</ins><span class="cx"> # Add current one to list
</span><del>- results.append(iter)
</del><ins>+ items.append(iter)
</ins><span class="cx">
</span><span class="cx"> # Check limits
</span><span class="cx"> if self.mUseCount:
</span><del>- # Exit if max count reached
- if len(results) >= self.mCount:
</del><ins>+ # Bump counter and exit if over
+ ctr += 1
+ if ctr >= self.mCount:
</ins><span class="cx"> return True
</span><span class="cx">
</span><ins>+ # Exit if after period we want
+ if range.isDateAfterPeriod(start_iter):
+ return False
</ins><span class="cx">
</span><ins>+ # Get next item
+ start_iter.recur(self.mFreq, self.mInterval, allow_invalid=True)
+
+
</ins><span class="cx"> def clear(self):
</span><span class="cx"> self.mCached = False
</span><span class="cx"> self.mFullyCached = False
</span><span class="lines">@@ -1189,7 +1065,8 @@
</span><span class="cx"> # IMPORTANT ExcludeFutureRecurrence assumes mCacheStart is setup with the
</span><span class="cx"> # owning VEVENT's DTSTART
</span><span class="cx"> # Currently this method is only called when a recurrence is being removed
</span><del>- # so the recurrence data should be cached
</del><ins>+ # so
+ # the recurrence data should be cached
</ins><span class="cx">
</span><span class="cx"> # Exclude dates on or after the chosen one
</span><span class="cx"> def excludeFutureRecurrence(self, exclude):
</span><span class="lines">@@ -1221,7 +1098,7 @@
</span><span class="cx"> # All possible BYxxx are valid, though some combinations are not
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> items[:] = self.byMonthExpand(items)
</span><span class="lines">@@ -1261,12 +1138,15 @@
</span><span class="cx"> if (self.mBySeconds is not None) and (len(self.mBySeconds) != 0):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateMonthlySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY and BYWEEKNO
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1303,12 +1183,15 @@
</span><span class="cx"> if ((self.mBySeconds is not None) and (len(self.mBySeconds) != 0)):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if ((self.mBySetPos is not None) and (len(self.mBySetPos) != 0)):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateWeeklySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY and BYMONTHDAY
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1337,12 +1220,15 @@
</span><span class="cx"> if (self.mBySeconds is not None) and (len(self.mBySeconds) != 0):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateDailySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1376,12 +1262,15 @@
</span><span class="cx"> if (self.mBySeconds is not None) and (len(self.mBySeconds) != 0):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateHourlySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1417,12 +1306,15 @@
</span><span class="cx"> if (self.mBySeconds is not None) and (len(self.mBySeconds) != 0):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateMinutelySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1460,12 +1352,15 @@
</span><span class="cx"> if (self.mBySeconds is not None) and (len(self.mBySeconds) != 0):
</span><span class="cx"> items[:] = self.bySecondExpand(items)
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def generateSecondlySet(self, start, items):
</span><span class="cx"> # Cannot have BYYEARDAY
</span><span class="cx">
</span><span class="cx"> # Start with initial date-time
</span><del>- items.append(start)
</del><ins>+ items.append(start.duplicate())
</ins><span class="cx">
</span><span class="cx"> if (self.mByMonth is not None) and (len(self.mByMonth) != 0):
</span><span class="cx"> # BYMONTH limits the range of possible values
</span><span class="lines">@@ -1505,7 +1400,10 @@
</span><span class="cx"> if (len(items) == 0):
</span><span class="cx"> return
</span><span class="cx">
</span><ins>+ if (self.mBySetPos is not None) and (len(self.mBySetPos) != 0):
+ items[:] = self.bySetPosLimit(items)
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def byMonthExpand(self, dates):
</span><span class="cx"> # Loop over all input items
</span><span class="cx"> output = []
</span><span class="lines">@@ -1514,7 +1412,7 @@
</span><span class="cx"> # insert into output
</span><span class="cx"> for iter2 in self.mByMonth:
</span><span class="cx"> temp = iter1.duplicate()
</span><del>- temp.setMonth(*iter2)
</del><ins>+ temp.setMonth(iter2)
</ins><span class="cx"> output.append(temp)
</span><span class="cx">
</span><span class="cx"> return output
</span><span class="lines">@@ -1683,40 +1581,125 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def byMonthLimit(self, dates):
</span><del>- # Keep each date that matches a BYMONTH
- return filter(lambda date: date.getMonth() in self.mByMonth, dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYMONTH and indicate keep if input month matches
+ keep = False
+ for iter2 in self.mByMonth:
+ keep = (iter1.getMonth() == iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def byWeekNoLimit(self, dates):
</span><del>- # Keep each date that matches a BYWEEKNO
- return filter(lambda date: any([date.isWeekNo(iter) for iter in self.mByWeekNo]), dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYWEEKNO and indicate keep if input month matches
+ keep = False
+ for iter2 in self.mByWeekNo:
+ keep = iter1.isWeekNo(iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def byMonthDayLimit(self, dates):
</span><del>- # Keep each date that matches a BYMONTHDAY
- return filter(lambda date: any([date.isMonthDay(iter) for iter in self.mByMonthDay]), dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYMONTHDAY and indicate keep if input month
+ # matches
+ keep = False
+ for iter2 in self.mByMonthDay:
+ keep = iter1.isMonthDay(iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def byDayLimit(self, dates):
</span><del>- # Keep each date that matches a BYDAY
- return filter(lambda date: any([date.isDayOfWeekInMonth(iter[0], iter[1]) for iter in self.mByDay]), dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYDAY and indicate keep if input month matches
+ keep = False
+ for iter2 in self.mByDay:
+ keep = iter1.isDayOfWeekInMonth(iter2[0], iter2[1])
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def byHourLimit(self, dates):
</span><del>- # Keep each date that matches a BYHOUR
- return filter(lambda date: date.getHours() in self.mByHours, dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYHOUR and indicate keep if input hour matches
+ keep = False
+ for iter2 in self.mByHours:
+ keep = (iter1.getHours() == iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def byMinuteLimit(self, dates):
</span><del>- # Keep each date that matches a BYMINUTE
- return filter(lambda date: date.getMinutes() in self.mByMinutes, dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYMINUTE and indicate keep if input minute matches
+ keep = False
+ for iter2 in self.mByMinutes:
+ keep = (iter1.getMinutes() == iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def bySecondLimit(self, dates):
</span><del>- # Keep each date that matches a BYSECOND
- return filter(lambda date: date.getSeconds() in self.mBySeconds, dates)
</del><ins>+ # Loop over all input items
+ output = []
+ for iter1 in dates:
+ # Loop over each BYSECOND and indicate keep if input second matches
+ keep = False
+ for iter2 in self.mBySeconds:
+ keep = (iter1.getSeconds() == iter2)
+ if keep:
+ break
</ins><span class="cx">
</span><ins>+ if keep:
+ output.append(iter1)
</ins><span class="cx">
</span><ins>+ return output
+
+
</ins><span class="cx"> def bySetPosLimit(self, dates):
</span><span class="cx"> # The input dates MUST be sorted in order for this to work properly
</span><span class="cx"> # dates.sort(cmp=DateTime.sort)
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarteststest_icudatetimepy"></a>
<div class="delfile"><h4>Deleted: PyCalendar/trunk/src/pycalendar/icalendar/tests/test_icudatetime.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/tests/test_icudatetime.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/tests/test_icudatetime.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -1,225 +0,0 @@
</span><del>-# coding: utf-8
-##
-# Copyright (c) 2007-2013 Cyrus Daboo. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import unittest
-from pycalendar.datetime import DateTime
-from pycalendar.icalendar.icudatetime import ICUDateTime
-
-class TestICUDateTime(unittest.TestCase):
- """
- Test L{ICUDateTime}
- """
-
- def testRoundtripDateText(self):
-
- data_date = (
- ("gregorian", 2011, 1, 2, False, "20110102",),
- ("gregorian", 1, 1, 2, False, "00010102",),
- ("chinese", 4651, 1, 1, False, "{C}46510101",),
- ("chinese", 4651, 9, 1, True, "{C}465109L01",),
- )
-
- for rscale, y, m, d, l, result in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- self.assertEqual(dt.getText(), result, "Failed on: %s" % (result,))
-
-
- def testRoundtripDateTime(self):
-
- data = (
- ("20110102", "gregorian", "20110102"),
- ("20110102T010203Z", "gregorian", "20110102T010203Z"),
- ("00010102", "gregorian", "00010102"),
- ("20140102", "chinese", "{C}46501202"),
- ("20140102T010203Z", "chinese", "{C}46501202T010203Z"),
- ("20141025", "chinese", "{C}465109L02"),
- ("20141025T010203", "chinese", "{C}465109L02T010203"),
- )
-
- for item, rscale, uitem in data:
- dt = DateTime.parseText(item, False)
- udt = ICUDateTime.fromDateTime(dt, rscale)
- self.assertEqual(udt.getText(), uitem, "Failed on icu: %s" % (uitem,))
- result = udt.toDateTime()
- self.assertEqual(result.getText(), item, "Failed on dt: %s" % (item,))
-
-
- def testSetYear(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 2013, "20130102", False,),
- ("gregorian", 2012, 2, 29, False, 2013, "20130301", True,),
- ("gregorian", 2012, 2, 29, False, 2016, "20160229", False,),
- )
-
- for rscale, y, m, d, l, year, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setYear(year)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(year, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(year, result, result_invalid,))
-
-
- def testOffsetYear(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 1, "20130102", False,),
- ("gregorian", 2012, 2, 29, False, 1, "20130228", False,),
- ("gregorian", 2012, 2, 29, False, 4, "20160229", False,),
- )
-
- for rscale, y, m, d, l, year, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.offsetYear(year)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(year, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(year, result, result_invalid,))
-
-
- def testSetMonth(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 2, "20120202", False,),
- ("gregorian", 2012, 1, 29, False, 2, "20120229", False,),
- ("gregorian", 2012, 1, 31, False, 2, "20120302", True,),
- ("gregorian", 2012, 2, 29, False, 3, "20120329", False,),
- )
-
- for rscale, y, m, d, l, month, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setMonth(month)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(month, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(month, result, result_invalid,))
-
-
- def testOffsetMonth(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 1, "20120202", False,),
- ("gregorian", 2012, 1, 29, False, 1, "20120229", False,),
- ("gregorian", 2012, 1, 31, False, 1, "20120229", False,),
- ("gregorian", 2012, 2, 29, False, 1, "20120329", False,),
- )
-
- for rscale, y, m, d, l, month, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.offsetMonth(month)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(month, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(month, result, result_invalid,))
-
-
- def testSetDay(self):
-
- data_date = (
- ("gregorian", 2012, 2, 1, False, 2, "20120202", False,),
- ("gregorian", 2012, 2, 1, False, 29, "20120229", False,),
- ("gregorian", 2012, 2, 1, False, 31, "20120302", True,),
- )
-
- for rscale, y, m, d, l, day, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setDay(day)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(day, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(day, result, result_invalid,))
-
-
- def testOffsetDay(self):
-
- data_date = (
- ("gregorian", 2012, 2, 1, False, 1, "20120202", False,),
- ("gregorian", 2012, 2, 1, False, 28, "20120229", False,),
- ("gregorian", 2012, 2, 1, False, 30, "20120302", False,),
- )
-
- for rscale, y, m, d, l, day, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.offsetDay(day)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(day, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(day, result, result_invalid,))
-
-
- def testYearDay(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 1, False, "20120101", False,),
- ("gregorian", 2012, 1, 2, False, 60, False, "20120229", False,),
- ("gregorian", 2012, 1, 2, False, 366, False, "20121231", False,),
- ("gregorian", 2012, 1, 2, False, 367, False, "20121231", False,),
- ("gregorian", 2012, 1, 2, False, 367, True, "20121231", True,),
- ("gregorian", 2012, 1, 2, False, -1, False, "20121231", False,),
- ("gregorian", 2012, 1, 2, False, -307, False, "20120229", False,),
- ("gregorian", 2012, 1, 2, False, -366, False, "20120101", False,),
- ("gregorian", 2012, 1, 2, False, -367, False, "20120101", False,),
- ("gregorian", 2012, 1, 2, False, -367, True, "20120101", True,),
- )
-
- for rscale, y, m, d, l, yearday, allow_invalid, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setYearDay(yearday, allow_invalid=allow_invalid)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(yearday, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(yearday, result, result_invalid,))
-
-
- def testMonthDay(self):
-
- data_date = (
- ("gregorian", 2012, 1, 2, False, 1, False, "20120101", False,),
- ("gregorian", 2012, 1, 31, False, 1, False, "20120101", False,),
- ("gregorian", 2012, 2, 1, False, 31, False, "20120229", False,),
- ("gregorian", 2012, 2, 1, False, 31, True, "20120229", True,),
- ("gregorian", 2012, 1, 2, False, -1, False, "20120131", False,),
- ("gregorian", 2012, 2, 29, False, -29, False, "20120201", False,),
- ("gregorian", 2012, 2, 29, False, -30, False, "20120201", False,),
- ("gregorian", 2012, 2, 29, False, -30, True, "20120201", True,),
- )
-
- for rscale, y, m, d, l, monthday, allow_invalid, result, result_invalid in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setMonthDay(monthday, allow_invalid=allow_invalid)
- self.assertEqual(dt.getText(), result, "Failed on: {} {} {}".format(monthday, result, result_invalid,))
- self.assertEqual(dt.invalid(), result_invalid, "Failed invalid on: {} {} {}".format(monthday, result, result_invalid,))
-
-
- def testWeekNum(self):
-
- data_date = (
- ("gregorian", 2012, 1, 3, False, 1, 2, "20120110",),
- ("gregorian", 2014, 1, 3, False, 1, 2, "20140110",),
- ("gregorian", 2012, 1, 1, False, 52, 2, "20120115",),
- )
-
- for rscale, y, m, d, l, start_weekno, weekno, result in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- self.assertEqual(dt.getWeekNo(), start_weekno)
- dt.setWeekNo(weekno)
- self.assertTrue(dt.isWeekNo(weekno))
- self.assertEqual(dt.getText(), result, "Failed on: {} {} vs {}".format(weekno, result, dt.getText(),))
-
-
- def testDayOfWeekInYear(self):
-
- data_date = (
- ("gregorian", 2012, 1, 3, False, 1, DateTime.SUNDAY, "20120101",),
- ("gregorian", 2012, 1, 3, False, 1, DateTime.MONDAY, "20120102",),
- ("gregorian", 2012, 1, 3, False, 2, DateTime.SUNDAY, "20120108",),
- ("gregorian", 2012, 1, 3, False, 10, DateTime.SUNDAY, "20120304",),
- ("gregorian", 2012, 1, 3, False, -1, DateTime.SUNDAY, "20121230",),
- ("gregorian", 2012, 1, 3, False, -45, DateTime.SUNDAY, "20120226",),
- )
-
- for rscale, y, m, d, l, offset, day, result in data_date:
- dt = ICUDateTime.fromDateComponents(rscale, y, m, d, l)
- dt.setDayOfWeekInYear(offset, day)
- self.assertEqual(dt.getText(), result, "Failed on: {} vs {}".format(result, dt.getText(),))
</del></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarteststest_recuriterpy"></a>
<div class="delfile"><h4>Deleted: PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recuriter.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recuriter.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recuriter.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -1,559 +0,0 @@
</span><del>-# coding: utf-8
-##
-# Copyright (c) 2007-2013 Cyrus Daboo. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from pycalendar.datetime import DateTime
-from pycalendar.icalendar import definitions
-from pycalendar.icalendar.icudatetime import ICUDateTime
-from pycalendar.icalendar.recuriter import RecurrenceIterator
-import unittest
-
-class MonthlySkips(object):
-
- def testMonthlySkipYes(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_MONTHLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_YES)
- results = [riter.next().getText() for _ in range(12)]
- self.assertEqual(
- results,
- [
- "20140131",
- "20140331",
- "20140531",
- "20140731",
- "20140831",
- "20141031",
- "20141231",
- "20150131",
- "20150331",
- "20150531",
- "20150731",
- "20150831",
- ]
- )
-
-
- def testMonthlySkipForward(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_MONTHLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_FORWARD)
- results = [riter.next().getText() for _ in range(12)]
- self.assertEqual(
- results,
- [
- "20140131",
- "20140301",
- "20140331",
- "20140501",
- "20140531",
- "20140701",
- "20140731",
- "20140831",
- "20141001",
- "20141031",
- "20141201",
- "20141231",
- ]
- )
-
-
- def testMonthlySkipBackward(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_MONTHLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_BACKWARD)
- results = [riter.next().getText() for _ in range(12)]
- self.assertEqual(
- results,
- [
- "20140131",
- "20140228",
- "20140331",
- "20140430",
- "20140531",
- "20140630",
- "20140731",
- "20140831",
- "20140930",
- "20141031",
- "20141130",
- "20141231",
- ]
- )
-
-
- def testMonthlySkipBackwardLeap(self):
-
- riter = RecurrenceIterator(self.dtleap, definitions.eRecurrence_MONTHLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_BACKWARD)
- results = [riter.next().getText() for _ in range(12)]
- self.assertEqual(
- results,
- [
- "20160131",
- "20160229",
- "20160331",
- "20160430",
- "20160531",
- "20160630",
- "20160731",
- "20160831",
- "20160930",
- "20161031",
- "20161130",
- "20161231",
- ]
- )
-
-
-
-class TestMonthlyDateTime(unittest.TestCase, MonthlySkips):
-
- def setUp(self):
- self.dt = DateTime(2014, 1, 31)
- self.dtleap = DateTime(2016, 1, 31)
- self.rscale = None
-
-
-
-class TestMonthlyGregorianICU(unittest.TestCase, MonthlySkips):
-
- def setUp(self):
- self.dt = ICUDateTime.fromDateComponents("gregorian", 2014, 1, 31)
- self.dtleap = ICUDateTime.fromDateComponents("gregorian", 2016, 1, 31)
- self.rscale = None
-
-
-
-class YearlySkipsOnLeapDay(object):
-
- def testYearlySkipYes(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_YEARLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_YES)
- results = [riter.next().getText() for _ in range(5)]
- self.assertEqual(
- results,
- [
- "20160229",
- "20200229",
- "20240229",
- "20280229",
- "20320229",
- ]
- )
-
-
- def testYearlySkipForward(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_YEARLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_FORWARD)
- results = [riter.next().getText() for _ in range(5)]
- self.assertEqual(
- results,
- [
- "20160229",
- "20170301",
- "20180301",
- "20190301",
- "20200229",
- ]
- )
-
-
- def testYearlySkipBackward(self):
-
- riter = RecurrenceIterator(self.dt, definitions.eRecurrence_YEARLY, 1, rscale=self.rscale, skip=definitions.eRecurrence_SKIP_BACKWARD)
- results = [riter.next().getText() for _ in range(5)]
- self.assertEqual(
- results,
- [
- "20160229",
- "20170228",
- "20180228",
- "20190228",
- "20200229",
- ]
- )
-
-
-
-class TestYearlyDateTime(unittest.TestCase, YearlySkipsOnLeapDay):
-
- def setUp(self):
- self.dt = DateTime(2016, 2, 29)
- self.rscale = None
-
-
-
-class TestYearlyGregorianICU(unittest.TestCase, YearlySkipsOnLeapDay):
-
- def setUp(self):
- self.dt = ICUDateTime.fromDateComponents("gregorian", 2016, 2, 29)
- self.rscale = None
-
-
-
-class TestMonthlyChineseICU(unittest.TestCase):
-
- def testMonthlyStartInLeapYearSkipYes(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30)
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale=None, skip=definitions.eRecurrence_SKIP_YES)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 4655:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "{C}46501230",
- "{C}46510230",
- "{C}46510430",
- "{C}46510630",
- "{C}46510830",
- "{C}46510930",
- "{C}46511030",
- "{C}46511230",
- "{C}46520230",
- "{C}46520530",
- "{C}46520730",
- "{C}46520830",
- "{C}46520930",
- "{C}46521130",
- "{C}46530130",
- "{C}46530330",
- "{C}46530630",
- "{C}46530830",
- "{C}46530930",
- "{C}46531130",
- "{C}46531230",
- "{C}46540230",
- "{C}46540430",
- "{C}465406L30",
- "{C}46540830",
- "{C}46541030",
- "{C}46541130",
- "{C}46541230",
- ]
- )
-
-
- def testMonthlyStartInLeapYearSkipForward(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30)
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale=None, skip=definitions.eRecurrence_SKIP_FORWARD)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 4655:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "{C}46501230",
- "{C}46510201",
- "{C}46510230",
- "{C}46510401",
- "{C}46510430",
- "{C}46510601",
- "{C}46510630",
- "{C}46510801",
- "{C}46510830",
- "{C}46510930",
- "{C}46511001",
- "{C}46511030",
- "{C}46511201",
- "{C}46511230",
- "{C}46520201",
- "{C}46520230",
- "{C}46520401",
- "{C}46520501",
- "{C}46520530",
- "{C}46520701",
- "{C}46520730",
- "{C}46520830",
- "{C}46520930",
- "{C}46521101",
- "{C}46521130",
- "{C}46530101",
- "{C}46530130",
- "{C}46530301",
- "{C}46530330",
- "{C}46530501",
- "{C}46530601",
- "{C}46530630",
- "{C}46530801",
- "{C}46530830",
- "{C}46530930",
- "{C}46531101",
- "{C}46531130",
- "{C}46531230",
- "{C}46540201",
- "{C}46540230",
- "{C}46540401",
- "{C}46540430",
- "{C}46540601",
- "{C}465406L01",
- "{C}465406L30",
- "{C}46540801",
- "{C}46540830",
- "{C}46541001",
- "{C}46541030",
- "{C}46541130",
- "{C}46541230",
- ]
- )
-
-
- def testMonthlyStartInLeapYearSkipBackward(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30)
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale=None, skip=definitions.eRecurrence_SKIP_BACKWARD)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 4655:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "{C}46501230",
- "{C}46510129",
- "{C}46510230",
- "{C}46510329",
- "{C}46510430",
- "{C}46510529",
- "{C}46510630",
- "{C}46510729",
- "{C}46510830",
- "{C}46510930",
- "{C}465109L29",
- "{C}46511030",
- "{C}46511129",
- "{C}46511230",
- "{C}46520129",
- "{C}46520230",
- "{C}46520329",
- "{C}46520429",
- "{C}46520530",
- "{C}46520629",
- "{C}46520730",
- "{C}46520830",
- "{C}46520930",
- "{C}46521029",
- "{C}46521130",
- "{C}46521229",
- "{C}46530130",
- "{C}46530229",
- "{C}46530330",
- "{C}46530429",
- "{C}46530529",
- "{C}46530630",
- "{C}46530729",
- "{C}46530830",
- "{C}46530930",
- "{C}46531029",
- "{C}46531130",
- "{C}46531230",
- "{C}46540129",
- "{C}46540230",
- "{C}46540329",
- "{C}46540430",
- "{C}46540529",
- "{C}46540629",
- "{C}465406L30",
- "{C}46540729",
- "{C}46540830",
- "{C}46540929",
- "{C}46541030",
- "{C}46541130",
- "{C}46541230",
- ]
- )
-
-
- def testMonthlyRscaleStartInLeapYearSkipYes(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30).toDateTime()
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale="chinese", skip=definitions.eRecurrence_SKIP_YES)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 2018:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "20140130",
- "20140330",
- "20140528",
- "20140726",
- "20140923",
- "20141023",
- "20141221",
- "20150218",
- "20150418",
- "20150715",
- "20150912",
- "20151012",
- "20151111",
- "20160109",
- "20160308",
- "20160506",
- "20160802",
- "20160930",
- "20161030",
- "20161228",
- "20170127",
- "20170327",
- "20170525",
- "20170821",
- "20171019",
- "20171217",
- ]
- )
-
-
- def testMonthlyRscaleStartInLeapYearSkipForward(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30).toDateTime()
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale="chinese", skip=definitions.eRecurrence_SKIP_FORWARD)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 2018:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "20140130",
- "20140301",
- "20140330",
- "20140429",
- "20140528",
- "20140627",
- "20140726",
- "20140825",
- "20140923",
- "20141023",
- "20141122",
- "20141221",
- "20150120",
- "20150218",
- "20150320",
- "20150418",
- "20150518",
- "20150616",
- "20150715",
- "20150814",
- "20150912",
- "20151012",
- "20151111",
- "20151211",
- "20160109",
- "20160208",
- "20160308",
- "20160407",
- "20160506",
- "20160605",
- "20160704",
- "20160802",
- "20160901",
- "20160930",
- "20161030",
- "20161129",
- "20161228",
- "20170127",
- "20170226",
- "20170327",
- "20170426",
- "20170525",
- "20170624",
- "20170723",
- "20170821",
- "20170920",
- "20171019",
- "20171118",
- "20171217",
- ]
- )
-
-
- def testMonthlyRscaleStartInLeapYearSkipBackward(self):
- dt = ICUDateTime.fromDateComponents("chinese", 4650, 12, 30).toDateTime()
-
- riter = RecurrenceIterator(dt, definitions.eRecurrence_MONTHLY, 1, rscale="chinese", skip=definitions.eRecurrence_SKIP_BACKWARD)
- results = []
- while True:
- result = riter.next()
- if result.getYear() >= 2018:
- break
- results.append(result.getText())
- self.assertEqual(
- results,
- [
- "20140130",
- "20140228",
- "20140330",
- "20140428",
- "20140528",
- "20140626",
- "20140726",
- "20140824",
- "20140923",
- "20141023",
- "20141121",
- "20141221",
- "20150119",
- "20150218",
- "20150319",
- "20150418",
- "20150517",
- "20150615",
- "20150715",
- "20150813",
- "20150912",
- "20151012",
- "20151111",
- "20151210",
- "20160109",
- "20160207",
- "20160308",
- "20160406",
- "20160506",
- "20160604",
- "20160703",
- "20160802",
- "20160831",
- "20160930",
- "20161030",
- "20161128",
- "20161228",
- "20170127",
- "20170225",
- "20170327",
- "20170425",
- "20170525",
- "20170623",
- "20170722",
- "20170821",
- "20170919",
- "20171019",
- "20171117",
- "20171217",
- ]
- )
</del></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarteststest_recurrencepy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recurrence.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recurrence.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/tests/test_recurrence.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -51,14 +51,6 @@
</span><span class="cx"> "FREQ=YEARLY;BYDAY=MO;BYWEEKNO=20",
</span><span class="cx"> "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
</span><span class="cx"> "FREQ=DAILY;BYMINUTE=0,20,40;BYHOUR=9,10,11,12,13,14,15,16",
</span><del>-
- # RSCALE
- "RSCALE=CHINESE;FREQ=DAILY",
- "RSCALE=GREGORIAN;FREQ=YEARLY;COUNT=400;SKIP=YES",
- "RSCALE=GREGORIAN;FREQ=YEARLY;COUNT=400;SKIP=BACKWARD",
- "RSCALE=GREGORIAN;FREQ=YEARLY;COUNT=400;SKIP=FORWARD",
- "RSCALE=CHINESE;FREQ=YEARLY;BYMONTH=5,6,6L,7",
-
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -67,7 +59,7 @@
</span><span class="cx"> for item in TestRecurrence.items:
</span><span class="cx"> recur = Recurrence()
</span><span class="cx"> recur.parse(item)
</span><del>- self.assertEqual(recur.getText(), item, "Failed to parse and re-generate '%s' '%s'" % (item, recur.getText()))
</del><ins>+ self.assertEqual(recur.getText(), item, "Failed to parse and re-generate '%s'" % (item,))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def testParseInvalid(self):
</span><span class="lines">@@ -86,8 +78,6 @@
</span><span class="cx"> "FREQ=MONTHLY;BYDAY=+1,3MO",
</span><span class="cx"> "FREQ=MONTHLY;BYHOUR=A",
</span><span class="cx"> "FREQ=MONTHLY;BYHOUR=54",
</span><del>- "FREQ=MONTHLY;SKIP=YES",
- "RSCALE=CHINESE;FREQ=MONTHLY;SKIP=NO",
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> for item in items:
</span><span class="lines">@@ -128,618 +118,153 @@
</span><span class="cx">
</span><span class="cx"> def testByWeekNoExpand(self):
</span><span class="cx">
</span><del>- rule = "FREQ=YEARLY;BYWEEKNO=1,2"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2013, 1, 1, 0, 0, 0)
- end = DateTime(2017, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2013, 1, 1, 0, 0, 0),
- DateTime(2013, 1, 8, 0, 0, 0),
- DateTime(2014, 1, 1, 0, 0, 0),
- DateTime(2014, 1, 8, 0, 0, 0),
- DateTime(2015, 1, 1, 0, 0, 0),
- DateTime(2015, 1, 8, 0, 0, 0),
- DateTime(2016, 1, 8, 0, 0, 0),
- DateTime(2016, 1, 15, 0, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyInvalidStart(self):
-
- rule = "FREQ=MONTHLY"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 40, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 2, 9, 12, 0, 0),
- DateTime(2014, 3, 9, 12, 0, 0),
- DateTime(2014, 4, 9, 12, 0, 0),
- DateTime(2014, 5, 9, 12, 0, 0),
- DateTime(2014, 6, 9, 12, 0, 0),
- DateTime(2014, 7, 9, 12, 0, 0),
- DateTime(2014, 8, 9, 12, 0, 0),
- DateTime(2014, 9, 9, 12, 0, 0),
- DateTime(2014, 10, 9, 12, 0, 0),
- DateTime(2014, 11, 9, 12, 0, 0),
- DateTime(2014, 12, 9, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testWeeklyTwice(self):
-
- rule = "FREQ=WEEKLY"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
- end = DateTime(2014, 2, 1, 0, 0, 0, tzid=Timezone(utc=True))
- items = []
- range = Period(start, end)
- recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 8, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 15, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 22, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 29, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
-
- ],
- msg="Failed: {}".format(rrule),
- )
-
- start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
- end = DateTime(2014, 3, 1, 0, 0, 0, tzid=Timezone(utc=True))
- items = []
- range = Period(start, end)
- recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 8, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 15, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 22, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 1, 29, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 2, 5, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 2, 12, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 2, 19, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 2, 26, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyInUTC(self):
-
- rule = "FREQ=MONTHLY"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
- end = DateTime(2015, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
- items = []
- range = Period(start, end)
- recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 2, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 3, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 4, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 5, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 6, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 7, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 8, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 9, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
- DateTime(2014, 10, 1, 12, 0, 0),
- DateTime(2014, 11, 1, 12, 0, 0),
- DateTime(2014, 12, 1, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyStart31st(self):
-
- rule = "FREQ=MONTHLY"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 31, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 31, 12, 0, 0),
- DateTime(2014, 3, 31, 12, 0, 0),
- DateTime(2014, 5, 31, 12, 0, 0),
- DateTime(2014, 7, 31, 12, 0, 0),
- DateTime(2014, 8, 31, 12, 0, 0),
- DateTime(2014, 10, 31, 12, 0, 0),
- DateTime(2014, 12, 31, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyByMonthDay31(self):
-
- rule = "FREQ=MONTHLY;BYMONTHDAY=31"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 31, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 31, 12, 0, 0),
- DateTime(2014, 3, 31, 12, 0, 0),
- DateTime(2014, 5, 31, 12, 0, 0),
- DateTime(2014, 7, 31, 12, 0, 0),
- DateTime(2014, 8, 31, 12, 0, 0),
- DateTime(2014, 10, 31, 12, 0, 0),
- DateTime(2014, 12, 31, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyByMonthDayMinus31(self):
-
- rule = "FREQ=MONTHLY;BYMONTHDAY=-31"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 1, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 1, 12, 0, 0),
- DateTime(2014, 3, 1, 12, 0, 0),
- DateTime(2014, 5, 1, 12, 0, 0),
- DateTime(2014, 7, 1, 12, 0, 0),
- DateTime(2014, 8, 1, 12, 0, 0),
- DateTime(2014, 10, 1, 12, 0, 0),
- DateTime(2014, 12, 1, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyByLastFridayExpand(self):
-
- rule = "FREQ=MONTHLY;BYDAY=-1FR"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 31, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 31, 12, 0, 0),
- DateTime(2014, 2, 28, 12, 0, 0),
- DateTime(2014, 3, 28, 12, 0, 0),
- DateTime(2014, 4, 25, 12, 0, 0),
- DateTime(2014, 5, 30, 12, 0, 0),
- DateTime(2014, 6, 27, 12, 0, 0),
- DateTime(2014, 7, 25, 12, 0, 0),
- DateTime(2014, 8, 29, 12, 0, 0),
- DateTime(2014, 9, 26, 12, 0, 0),
- DateTime(2014, 10, 31, 12, 0, 0),
- DateTime(2014, 11, 28, 12, 0, 0),
- DateTime(2014, 12, 26, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testMonthlyByFifthFridayExpand(self):
-
- rule = "FREQ=MONTHLY;BYDAY=5FR"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 31, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 31, 12, 0, 0),
- DateTime(2014, 5, 30, 12, 0, 0),
- DateTime(2014, 8, 29, 12, 0, 0),
- DateTime(2014, 10, 31, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testYearlyLeapDay(self):
-
- rule = "FREQ=YEARLY"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2012, 2, 29, 12, 0, 0)
- end = DateTime(2020, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2012, 2, 29, 12, 0, 0),
- DateTime(2016, 2, 29, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testYearlyYearDay(self):
-
- rule = "FREQ=YEARLY;BYYEARDAY=366"
- for rrule in (
- rule,
- "RSCALE=GREGORIAN;{};SKIP=YES".format(rule)
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2012, 12, 31, 12, 0, 0)
- end = DateTime(2020, 1, 1, 0, 0, 0)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2012, 12, 31, 12, 0, 0),
- DateTime(2016, 12, 31, 12, 0, 0),
- ],
- msg="Failed: {}".format(rrule),
- )
-
-
- def testClearOnChange(self):
-
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse("FREQ=DAILY")
-
</del><ins>+ recur.parse("FREQ=YEARLY;BYWEEKNO=1,2")
</ins><span class="cx"> start = DateTime(2013, 1, 1, 0, 0, 0)
</span><span class="cx"> end = DateTime(2017, 1, 1, 0, 0, 0)
</span><del>- range = Period(start, end)
</del><span class="cx"> items = []
</span><ins>+ range = Period(start, end)
</ins><span class="cx"> recur.expand(start, range, items)
</span><del>- self.assertTrue(recur.mCached)
- self.assertTrue(len(items) > 100)
</del><ins>+ self.assertEqual(
+ items,
+ [
+ DateTime(2013, 1, 1, 0, 0, 0),
+ DateTime(2013, 1, 8, 0, 0, 0),
+ DateTime(2014, 1, 1, 0, 0, 0),
+ DateTime(2014, 1, 8, 0, 0, 0),
+ DateTime(2015, 1, 1, 0, 0, 0),
+ DateTime(2015, 1, 8, 0, 0, 0),
+ DateTime(2016, 1, 8, 0, 0, 0),
+ DateTime(2016, 1, 15, 0, 0, 0),
+ ],
+ )
</ins><span class="cx">
</span><del>- recur.setUseCount(True)
- recur.setCount(10)
- self.assertFalse(recur.mCached)
- items = []
- recur.expand(start, range, items)
- self.assertEqual(len(items), 10)
</del><span class="cx">
</span><ins>+ def testMonthlyInvalidStart(self):
</ins><span class="cx">
</span><del>-
-class TestRecurrenceRscale(unittest.TestCase):
-
- def testMonthlyRscaleStartInLeapYearSkipYes(self):
-
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse("RSCALE=CHINESE;FREQ=MONTHLY;SKIP=YES")
- start = DateTime(2014, 1, 30) # {C}46501230
- end = DateTime(2018, 1, 1)
</del><ins>+ recur.parse("FREQ=MONTHLY")
+ start = DateTime(2014, 1, 40, 12, 0, 0)
+ end = DateTime(2015, 1, 1, 0, 0, 0)
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="cx"> recur.expand(start, range, items)
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30),
- DateTime(2014, 3, 30),
- DateTime(2014, 5, 28),
- DateTime(2014, 7, 26),
- DateTime(2014, 9, 23),
- DateTime(2014, 10, 23),
- DateTime(2014, 12, 21),
- DateTime(2015, 2, 18),
- DateTime(2015, 4, 18),
- DateTime(2015, 7, 15),
- DateTime(2015, 9, 12),
- DateTime(2015, 10, 12),
- DateTime(2015, 11, 11),
- DateTime(2016, 1, 9),
- DateTime(2016, 3, 8),
- DateTime(2016, 5, 6),
- DateTime(2016, 8, 2),
- DateTime(2016, 9, 30),
- DateTime(2016, 10, 30),
- DateTime(2016, 12, 28),
- DateTime(2017, 1, 27),
- DateTime(2017, 3, 27),
- DateTime(2017, 5, 25),
- DateTime(2017, 8, 21),
- DateTime(2017, 10, 19),
- DateTime(2017, 12, 17),
</del><ins>+ DateTime(2014, 2, 9, 12, 0, 0),
+ DateTime(2014, 3, 9, 12, 0, 0),
+ DateTime(2014, 4, 9, 12, 0, 0),
+ DateTime(2014, 5, 9, 12, 0, 0),
+ DateTime(2014, 6, 9, 12, 0, 0),
+ DateTime(2014, 7, 9, 12, 0, 0),
+ DateTime(2014, 8, 9, 12, 0, 0),
+ DateTime(2014, 9, 9, 12, 0, 0),
+ DateTime(2014, 10, 9, 12, 0, 0),
+ DateTime(2014, 11, 9, 12, 0, 0),
+ DateTime(2014, 12, 9, 12, 0, 0),
</ins><span class="cx"> ],
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testMonthlyRscaleStartInLeapYearSkipForward(self):
</del><ins>+ def testWeeklyTwice(self):
</ins><span class="cx">
</span><span class="cx"> recur = Recurrence()
</span><del>- recur.parse("RSCALE=CHINESE;FREQ=MONTHLY;SKIP=FORWARD")
- start = DateTime(2014, 1, 30) # {C}46501230
- end = DateTime(2018, 1, 1)
</del><ins>+ recur.parse("FREQ=WEEKLY")
+ start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
+ end = DateTime(2014, 2, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><del>- recur.expand(start, range, items)
</del><ins>+ recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
</ins><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30),
- DateTime(2014, 3, 1),
- DateTime(2014, 3, 30),
- DateTime(2014, 4, 29),
- DateTime(2014, 5, 28),
- DateTime(2014, 6, 27),
- DateTime(2014, 7, 26),
- DateTime(2014, 8, 25),
- DateTime(2014, 9, 23),
- DateTime(2014, 10, 23),
- DateTime(2014, 11, 22),
- DateTime(2014, 12, 21),
- DateTime(2015, 1, 20),
- DateTime(2015, 2, 18),
- DateTime(2015, 3, 20),
- DateTime(2015, 4, 18),
- DateTime(2015, 5, 18),
- DateTime(2015, 6, 16),
- DateTime(2015, 7, 15),
- DateTime(2015, 8, 14),
- DateTime(2015, 9, 12),
- DateTime(2015, 10, 12),
- DateTime(2015, 11, 11),
- DateTime(2015, 12, 11),
- DateTime(2016, 1, 9),
- DateTime(2016, 2, 8),
- DateTime(2016, 3, 8),
- DateTime(2016, 4, 7),
- DateTime(2016, 5, 6),
- DateTime(2016, 6, 5),
- DateTime(2016, 7, 4),
- DateTime(2016, 8, 2),
- DateTime(2016, 9, 1),
- DateTime(2016, 9, 30),
- DateTime(2016, 10, 30),
- DateTime(2016, 11, 29),
- DateTime(2016, 12, 28),
- DateTime(2017, 1, 27),
- DateTime(2017, 2, 26),
- DateTime(2017, 3, 27),
- DateTime(2017, 4, 26),
- DateTime(2017, 5, 25),
- DateTime(2017, 6, 24),
- DateTime(2017, 7, 23),
- DateTime(2017, 8, 21),
- DateTime(2017, 9, 20),
- DateTime(2017, 10, 19),
- DateTime(2017, 11, 18),
- DateTime(2017, 12, 17),
</del><ins>+ DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 8, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 15, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 22, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 29, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+
</ins><span class="cx"> ],
</span><span class="cx"> )
</span><span class="cx">
</span><ins>+ start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
+ end = DateTime(2014, 3, 1, 0, 0, 0, tzid=Timezone(utc=True))
+ items = []
+ range = Period(start, end)
+ recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
+ self.assertEqual(
+ items,
+ [
+ DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 8, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 15, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 22, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 1, 29, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 2, 5, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 2, 12, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 2, 19, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 2, 26, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ ],
+ )
</ins><span class="cx">
</span><del>- def testMonthlyRscaleStartInLeapYearSkipBackwardDefault(self):
</del><span class="cx">
</span><del>- for rrule in (
- "RSCALE=CHINESE;FREQ=MONTHLY;SKIP=BACKWARD",
- "RSCALE=CHINESE;FREQ=MONTHLY"
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2014, 1, 30) # {C}46501230
- end = DateTime(2018, 1, 1)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2014, 1, 30),
- DateTime(2014, 2, 28),
- DateTime(2014, 3, 30),
- DateTime(2014, 4, 28),
- DateTime(2014, 5, 28),
- DateTime(2014, 6, 26),
- DateTime(2014, 7, 26),
- DateTime(2014, 8, 24),
- DateTime(2014, 9, 23),
- DateTime(2014, 10, 23),
- DateTime(2014, 11, 21),
- DateTime(2014, 12, 21),
- DateTime(2015, 1, 19),
- DateTime(2015, 2, 18),
- DateTime(2015, 3, 19),
- DateTime(2015, 4, 18),
- DateTime(2015, 5, 17),
- DateTime(2015, 6, 15),
- DateTime(2015, 7, 15),
- DateTime(2015, 8, 13),
- DateTime(2015, 9, 12),
- DateTime(2015, 10, 12),
- DateTime(2015, 11, 11),
- DateTime(2015, 12, 10),
- DateTime(2016, 1, 9),
- DateTime(2016, 2, 7),
- DateTime(2016, 3, 8),
- DateTime(2016, 4, 6),
- DateTime(2016, 5, 6),
- DateTime(2016, 6, 4),
- DateTime(2016, 7, 3),
- DateTime(2016, 8, 2),
- DateTime(2016, 8, 31),
- DateTime(2016, 9, 30),
- DateTime(2016, 10, 30),
- DateTime(2016, 11, 28),
- DateTime(2016, 12, 28),
- DateTime(2017, 1, 27),
- DateTime(2017, 2, 25),
- DateTime(2017, 3, 27),
- DateTime(2017, 4, 25),
- DateTime(2017, 5, 25),
- DateTime(2017, 6, 23),
- DateTime(2017, 7, 22),
- DateTime(2017, 8, 21),
- DateTime(2017, 9, 19),
- DateTime(2017, 10, 19),
- DateTime(2017, 11, 17),
- DateTime(2017, 12, 17),
- ],
- )
</del><ins>+ def testMonthlyInUTC(self):
</ins><span class="cx">
</span><del>-
- def testYearlyLeapDaySkipYes(self):
-
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse("RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=YES;COUNT=5")
- start = DateTime(2016, 2, 29)
- end = DateTime(2100, 1, 1)
</del><ins>+ recur.parse("FREQ=MONTHLY")
+ start = DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(utc=True))
+ end = DateTime(2015, 1, 1, 0, 0, 0, tzid=Timezone(utc=True))
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><del>- recur.expand(start, range, items)
</del><ins>+ recur.expand(DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")), range, items)
</ins><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2016, 2, 29),
- DateTime(2020, 2, 29),
- DateTime(2024, 2, 29),
- DateTime(2028, 2, 29),
- DateTime(2032, 2, 29),
- ]
</del><ins>+ DateTime(2014, 1, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 2, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 3, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 4, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 5, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 6, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 7, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 8, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 9, 1, 12, 0, 0, tzid=Timezone(tzid="America/New_York")),
+ DateTime(2014, 10, 1, 12, 0, 0),
+ DateTime(2014, 11, 1, 12, 0, 0),
+ DateTime(2014, 12, 1, 12, 0, 0),
+ ],
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testYearlyLeapDaySkipForward(self):
</del><ins>+ def testMonthlyStart31st(self):
</ins><span class="cx">
</span><span class="cx"> recur = Recurrence()
</span><del>- recur.parse("RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=FORWARD;COUNT=5")
- start = DateTime(2016, 2, 29)
- end = DateTime(2100, 1, 1)
</del><ins>+ recur.parse("FREQ=MONTHLY")
+ start = DateTime(2014, 1, 31, 12, 0, 0)
+ end = DateTime(2015, 1, 1, 0, 0, 0)
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="cx"> recur.expand(start, range, items)
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2016, 2, 29),
- DateTime(2017, 3, 1),
- DateTime(2018, 3, 1),
- DateTime(2019, 3, 1),
- DateTime(2020, 2, 29),
- ]
</del><ins>+ DateTime(2014, 1, 31, 12, 0, 0),
+ DateTime(2014, 3, 31, 12, 0, 0),
+ DateTime(2014, 5, 31, 12, 0, 0),
+ DateTime(2014, 7, 31, 12, 0, 0),
+ DateTime(2014, 8, 31, 12, 0, 0),
+ DateTime(2014, 10, 31, 12, 0, 0),
+ DateTime(2014, 12, 31, 12, 0, 0),
+ ],
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testYearlyLeapDaySkipBackwardDefault(self):
</del><ins>+ def testMonthlyByMonthDay31(self):
</ins><span class="cx">
</span><del>- for rrule in (
- "RSCALE=GREGORIAN;FREQ=YEARLY;SKIP=BACKWARD;COUNT=5",
- "RSCALE=GREGORIAN;FREQ=YEARLY;COUNT=5",
- ):
- recur = Recurrence()
- recur.parse(rrule)
- start = DateTime(2016, 2, 29)
- end = DateTime(2100, 1, 1)
- items = []
- range = Period(start, end)
- recur.expand(start, range, items)
- self.assertEqual(
- items,
- [
- DateTime(2016, 2, 29),
- DateTime(2017, 2, 28),
- DateTime(2018, 2, 28),
- DateTime(2019, 2, 28),
- DateTime(2020, 2, 29),
- ]
- )
-
-
- def testChineseMonthlyByMonthDay30SkipYes(self):
-
- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=30;SKIP=YES"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
</del><ins>+ recur.parse("FREQ=MONTHLY;BYMONTHDAY=31")
+ start = DateTime(2014, 1, 31, 12, 0, 0)
</ins><span class="cx"> end = DateTime(2015, 1, 1, 0, 0, 0)
</span><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="lines">@@ -747,24 +272,22 @@
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30, 12, 0, 0),
- DateTime(2014, 3, 30, 12, 0, 0),
- DateTime(2014, 5, 28, 12, 0, 0),
- DateTime(2014, 7, 26, 12, 0, 0),
- DateTime(2014, 9, 23, 12, 0, 0),
- DateTime(2014, 10, 23, 12, 0, 0),
- DateTime(2014, 12, 21, 12, 0, 0),
</del><ins>+ DateTime(2014, 1, 31, 12, 0, 0),
+ DateTime(2014, 3, 31, 12, 0, 0),
+ DateTime(2014, 5, 31, 12, 0, 0),
+ DateTime(2014, 7, 31, 12, 0, 0),
+ DateTime(2014, 8, 31, 12, 0, 0),
+ DateTime(2014, 10, 31, 12, 0, 0),
+ DateTime(2014, 12, 31, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testChineseMonthlyByMonthDay30SkipBackward(self):
</del><ins>+ def testMonthlyByMonthDayMinus31(self):
</ins><span class="cx">
</span><del>- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=30;SKIP=BACKWARD"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
</del><ins>+ recur.parse("FREQ=MONTHLY;BYMONTHDAY=-31")
+ start = DateTime(2014, 1, 1, 12, 0, 0)
</ins><span class="cx"> end = DateTime(2015, 1, 1, 0, 0, 0)
</span><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="lines">@@ -772,29 +295,22 @@
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30, 12, 0, 0),
- DateTime(2014, 2, 28, 12, 0, 0),
- DateTime(2014, 3, 30, 12, 0, 0),
- DateTime(2014, 4, 28, 12, 0, 0),
- DateTime(2014, 5, 28, 12, 0, 0),
- DateTime(2014, 6, 26, 12, 0, 0),
- DateTime(2014, 7, 26, 12, 0, 0),
- DateTime(2014, 8, 24, 12, 0, 0),
- DateTime(2014, 9, 23, 12, 0, 0),
- DateTime(2014, 10, 23, 12, 0, 0),
- DateTime(2014, 11, 21, 12, 0, 0),
- DateTime(2014, 12, 21, 12, 0, 0),
</del><ins>+ DateTime(2014, 1, 1, 12, 0, 0),
+ DateTime(2014, 3, 1, 12, 0, 0),
+ DateTime(2014, 5, 1, 12, 0, 0),
+ DateTime(2014, 7, 1, 12, 0, 0),
+ DateTime(2014, 8, 1, 12, 0, 0),
+ DateTime(2014, 10, 1, 12, 0, 0),
+ DateTime(2014, 12, 1, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testChineseMonthlyByMonthDay30SkipForward(self):
</del><ins>+ def testMonthlyByLastFridayExpand(self):
</ins><span class="cx">
</span><del>- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=30;SKIP=FORWARD"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
</del><ins>+ recur.parse("FREQ=MONTHLY;BYDAY=-1FR")
+ start = DateTime(2014, 1, 31, 12, 0, 0)
</ins><span class="cx"> end = DateTime(2015, 1, 1, 0, 0, 0)
</span><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="lines">@@ -802,29 +318,27 @@
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30, 12, 0, 0),
- DateTime(2014, 3, 1, 12, 0, 0),
- DateTime(2014, 3, 30, 12, 0, 0),
- DateTime(2014, 4, 29, 12, 0, 0),
- DateTime(2014, 5, 28, 12, 0, 0),
</del><ins>+ DateTime(2014, 1, 31, 12, 0, 0),
+ DateTime(2014, 2, 28, 12, 0, 0),
+ DateTime(2014, 3, 28, 12, 0, 0),
+ DateTime(2014, 4, 25, 12, 0, 0),
+ DateTime(2014, 5, 30, 12, 0, 0),
</ins><span class="cx"> DateTime(2014, 6, 27, 12, 0, 0),
</span><del>- DateTime(2014, 7, 26, 12, 0, 0),
- DateTime(2014, 8, 25, 12, 0, 0),
- DateTime(2014, 9, 23, 12, 0, 0),
- DateTime(2014, 10, 23, 12, 0, 0),
- DateTime(2014, 11, 22, 12, 0, 0),
- DateTime(2014, 12, 21, 12, 0, 0),
</del><ins>+ DateTime(2014, 7, 25, 12, 0, 0),
+ DateTime(2014, 8, 29, 12, 0, 0),
+ DateTime(2014, 9, 26, 12, 0, 0),
+ DateTime(2014, 10, 31, 12, 0, 0),
+ DateTime(2014, 11, 28, 12, 0, 0),
+ DateTime(2014, 12, 26, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testChineseMonthlyByMonthDayMinus30SkipYes(self):
</del><ins>+ def testMonthlyByFifthFridayExpand(self):
</ins><span class="cx">
</span><del>- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=-30;SKIP=YES"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
</del><ins>+ recur.parse("FREQ=MONTHLY;BYDAY=5FR")
+ start = DateTime(2014, 1, 31, 12, 0, 0)
</ins><span class="cx"> end = DateTime(2015, 1, 1, 0, 0, 0)
</span><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="lines">@@ -832,72 +346,66 @@
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 3, 1, 12, 0, 0),
- DateTime(2014, 4, 29, 12, 0, 0),
- DateTime(2014, 6, 27, 12, 0, 0),
- DateTime(2014, 8, 25, 12, 0, 0),
- DateTime(2014, 9, 24, 12, 0, 0),
- DateTime(2014, 11, 22, 12, 0, 0),
</del><ins>+ DateTime(2014, 1, 31, 12, 0, 0),
+ DateTime(2014, 5, 30, 12, 0, 0),
+ DateTime(2014, 8, 29, 12, 0, 0),
+ DateTime(2014, 10, 31, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testChineseMonthlyByMonthDayMinus30SkipBackward(self):
</del><ins>+ def testYearlyLeapDay(self):
</ins><span class="cx">
</span><del>- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=-30;SKIP=BACKWARD"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
</del><ins>+ recur.parse("FREQ=YEARLY")
+ start = DateTime(2012, 2, 29, 12, 0, 0)
+ end = DateTime(2020, 1, 1, 0, 0, 0)
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="cx"> recur.expand(start, range, items)
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 30, 12, 0, 0),
- DateTime(2014, 3, 1, 12, 0, 0),
- DateTime(2014, 3, 30, 12, 0, 0),
- DateTime(2014, 4, 29, 12, 0, 0),
- DateTime(2014, 5, 28, 12, 0, 0),
- DateTime(2014, 6, 27, 12, 0, 0),
- DateTime(2014, 7, 26, 12, 0, 0),
- DateTime(2014, 8, 25, 12, 0, 0),
- DateTime(2014, 9, 24, 12, 0, 0),
- DateTime(2014, 10, 23, 12, 0, 0),
- DateTime(2014, 11, 22, 12, 0, 0),
- DateTime(2014, 12, 21, 12, 0, 0),
</del><ins>+ DateTime(2012, 2, 29, 12, 0, 0),
+ DateTime(2016, 2, 29, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><del>- def testChineseMonthlyByMonthDayMinus30SkipForward(self):
</del><ins>+ def testYearlyYearDay(self):
</ins><span class="cx">
</span><del>- rrule = "RSCALE=CHINESE;FREQ=MONTHLY;BYMONTHDAY=-30;SKIP=FORWARD"
</del><span class="cx"> recur = Recurrence()
</span><del>- recur.parse(rrule)
- start = DateTime(2014, 1, 30, 12, 0, 0)
- end = DateTime(2015, 1, 1, 0, 0, 0)
</del><ins>+ recur.parse("FREQ=YEARLY;BYYEARDAY=366")
+ start = DateTime(2012, 12, 31, 12, 0, 0)
+ end = DateTime(2020, 1, 1, 0, 0, 0)
</ins><span class="cx"> items = []
</span><span class="cx"> range = Period(start, end)
</span><span class="cx"> recur.expand(start, range, items)
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> items,
</span><span class="cx"> [
</span><del>- DateTime(2014, 1, 31, 12, 0, 0),
- DateTime(2014, 3, 1, 12, 0, 0),
- DateTime(2014, 3, 31, 12, 0, 0),
- DateTime(2014, 4, 29, 12, 0, 0),
- DateTime(2014, 5, 29, 12, 0, 0),
- DateTime(2014, 6, 27, 12, 0, 0),
- DateTime(2014, 7, 27, 12, 0, 0),
- DateTime(2014, 8, 25, 12, 0, 0),
- DateTime(2014, 9, 24, 12, 0, 0),
- DateTime(2014, 10, 24, 12, 0, 0),
- DateTime(2014, 11, 22, 12, 0, 0),
- DateTime(2014, 12, 22, 12, 0, 0),
</del><ins>+ DateTime(2012, 12, 31, 12, 0, 0),
+ DateTime(2016, 12, 31, 12, 0, 0),
</ins><span class="cx"> ],
</span><del>- msg="Failed: {} {}".format(rrule, items,),
</del><span class="cx"> )
</span><ins>+
+
+ def testClearOnChange(self):
+
+ recur = Recurrence()
+ recur.parse("FREQ=DAILY")
+
+ start = DateTime(2013, 1, 1, 0, 0, 0)
+ end = DateTime(2017, 1, 1, 0, 0, 0)
+ range = Period(start, end)
+ items = []
+ recur.expand(start, range, items)
+ self.assertTrue(recur.mCached)
+ self.assertTrue(len(items) > 100)
+
+ recur.setUseCount(True)
+ recur.setCount(10)
+ self.assertFalse(recur.mCached)
+ items = []
+ recur.expand(start, range, items)
+ self.assertEqual(len(items), 10)
</ins></span></pre></div>
<a id="PyCalendartrunksrcpycalendaricalendarxmldefinitionspy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/icalendar/xmldefinitions.py (14192 => 14193)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/icalendar/xmldefinitions.py        2014-12-01 16:26:51 UTC (rev 14192)
+++ PyCalendar/trunk/src/pycalendar/icalendar/xmldefinitions.py        2014-12-01 16:50:49 UTC (rev 14193)
</span><span class="lines">@@ -22,8 +22,6 @@
</span><span class="cx">
</span><span class="cx"> value_recur = "recur"
</span><span class="cx">
</span><del>-recur_rscale = "rscale"
-
</del><span class="cx"> recur_freq = "freq"
</span><span class="cx"> recur_freq_secondly = "SECONDLY"
</span><span class="cx"> recur_freq_minutely = "MINUTELY"
</span><span class="lines">@@ -37,11 +35,6 @@
</span><span class="cx"> recur_until = "until"
</span><span class="cx"> recur_interval = "interval"
</span><span class="cx">
</span><del>-recur_skip = "skip"
-recur_skip_yes = "yes"
-recur_skip_backward = "backward"
-recur_skip_forward = "forward"
-
</del><span class="cx"> recur_bysecond = "bysecond"
</span><span class="cx"> recur_byminute = "byminute"
</span><span class="cx"> recur_byhour = "byhour"
</span></span></pre>
</div>
</div>
</body>
</html>