<!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>[14695] PyCalendar/trunk/src/pycalendar</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/14695">14695</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-04-22 08:58:34 -0700 (Wed, 22 Apr 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Performance optimizations.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#PyCalendartrunksrcpycalendardatetimepy">PyCalendar/trunk/src/pycalendar/datetime.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendarperiodpy">PyCalendar/trunk/src/pycalendar/period.py</a></li>
<li><a href="#PyCalendartrunksrcpycalendartimezonepy">PyCalendar/trunk/src/pycalendar/timezone.py</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#PyCalendartrunksrcpycalendarteststest_periodpy">PyCalendar/trunk/src/pycalendar/tests/test_period.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="PyCalendartrunksrcpycalendardatetimepy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/datetime.py (14694 => 14695)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/datetime.py        2015-04-21 22:54:54 UTC (rev 14694)
+++ PyCalendar/trunk/src/pycalendar/datetime.py        2015-04-22 15:58:34 UTC (rev 14695)
</span><span class="lines">@@ -50,38 +50,50 @@
</span><span class="cx">
</span><span class="cx"> def __init__(self, year=None, month=None, day=None, hours=None, minutes=None, seconds=None, tzid=None, utcoffset=None):
</span><span class="cx">
</span><del>- self.mYear = 1970
- self.mMonth = 1
- self.mDay = 1
-
- self.mHours = 0
- self.mMinutes = 0
- self.mSeconds = 0
-
- self.mDateOnly = False
-
- self.mTZUTC = False
- self.mTZID = None
- self.mTZOffset = None
-
- self.mPosixTimeCached = False
- self.mPosixTime = 0
-
</del><span class="cx"> if (year is not None) and (month is not None) and (day is not None):
</span><ins>+
</ins><span class="cx"> self.mYear = year
</span><span class="cx"> self.mMonth = month
</span><span class="cx"> self.mDay = day
</span><ins>+
</ins><span class="cx"> if (hours is not None) and (minutes is not None) and (seconds is not None):
</span><span class="cx"> self.mHours = hours
</span><span class="cx"> self.mMinutes = minutes
</span><span class="cx"> self.mSeconds = seconds
</span><ins>+ self.mDateOnly = False
</ins><span class="cx"> else:
</span><ins>+ self.mHours = 0
+ self.mMinutes = 0
+ self.mSeconds = 0
</ins><span class="cx"> self.mDateOnly = True
</span><ins>+
</ins><span class="cx"> if tzid:
</span><span class="cx"> self.mTZUTC = tzid.getUTC()
</span><span class="cx"> self.mTZID = tzid.getTimezoneID()
</span><ins>+ else:
+ self.mTZUTC = False
+ self.mTZID = None
+ self.mTZOffset = None
</ins><span class="cx">
</span><ins>+ else:
+ self.mYear = 1970
+ self.mMonth = 1
+ self.mDay = 1
</ins><span class="cx">
</span><ins>+ self.mHours = 0
+ self.mMinutes = 0
+ self.mSeconds = 0
+
+ self.mDateOnly = False
+
+ self.mTZUTC = False
+ self.mTZID = None
+ self.mTZOffset = None
+
+ self.mPosixTimeCached = False
+ self.mPosixTime = 0
+
+
</ins><span class="cx"> def duplicate(self):
</span><span class="cx"> other = DateTime(self.mYear, self.mMonth, self.mDay, self.mHours, self.mMinutes, self.mSeconds)
</span><span class="cx">
</span><span class="lines">@@ -194,76 +206,31 @@
</span><span class="cx"> return 1
</span><span class="cx"> # If either are date only, then just do date compare
</span><span class="cx"> if self.mDateOnly or comp.mDateOnly:
</span><del>- if self.mYear == comp.mYear:
- if self.mMonth == comp.mMonth:
- if self.mDay == comp.mDay:
- return 0
- else:
- if self.mDay < comp.mDay:
- return -1
- else:
- return 1
- else:
- if self.mMonth < comp.mMonth:
- return -1
- else:
- return 1
- else:
- if self.mYear < comp.mYear:
- return -1
- else:
- return 1
</del><ins>+ c = cmp(self.mYear, comp.mYear)
+ if c == 0:
+ c = cmp(self.mMonth, comp.mMonth)
+ if c == 0:
+ c = cmp(self.mDay, comp.mDay)
+ return c
</ins><span class="cx">
</span><span class="cx"> # If they have the same timezone do simple compare - no posix calc
</span><span class="cx"> # needed
</span><span class="cx"> elif (Timezone.same(self.mTZUTC, self.mTZID, comp.mTZUTC, comp.mTZID)):
</span><del>- if self.mYear == comp.mYear:
- if self.mMonth == comp.mMonth:
- if self.mDay == comp.mDay:
- if self.mHours == comp.mHours:
- if self.mMinutes == comp.mMinutes:
- if self.mSeconds == comp.mSeconds:
- return 0
- else:
- if self.mSeconds < comp.mSeconds:
- return -1
- else:
- return 1
- else:
- if self.mMinutes < comp.mMinutes:
- return -1
- else:
- return 1
- else:
- if self.mHours < comp.mHours:
- return -1
- else:
- return 1
- else:
- if self.mDay < comp.mDay:
- return -1
- else:
- return 1
- else:
- if self.mMonth < comp.mMonth:
- return -1
- else:
- return 1
- else:
- if self.mYear < comp.mYear:
- return -1
- else:
- return 1
</del><ins>+ c = cmp(self.mYear, comp.mYear)
+ if c == 0:
+ c = cmp(self.mMonth, comp.mMonth)
+ if c == 0:
+ c = cmp(self.mDay, comp.mDay)
+ if c == 0:
+ c = cmp(self.mHours, comp.mHours)
+ if c == 0:
+ c = cmp(self.mMinutes, comp.mMinutes)
+ if c == 0:
+ c = cmp(self.mSeconds, comp.mSeconds)
+ return c
+
</ins><span class="cx"> else:
</span><del>- posix1 = self.getPosixTime()
- posix2 = comp.getPosixTime()
- if posix1 == posix2:
- return 0
- else:
- if posix1 < posix2:
- return -1
- else:
- return 1
</del><ins>+ return cmp(self.getPosixTime(), comp.getPosixTime())
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def compareDate(self, comp):
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendarperiodpy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/period.py (14694 => 14695)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/period.py        2015-04-21 22:54:54 UTC (rev 14694)
+++ PyCalendar/trunk/src/pycalendar/period.py        2015-04-22 15:58:34 UTC (rev 14695)
</span><span class="lines">@@ -28,26 +28,28 @@
</span><span class="cx">
</span><span class="cx"> if end is not None:
</span><span class="cx"> self.mEnd = end
</span><del>- self.mDuration = self.mEnd - self.mStart
</del><ins>+ self.mDuration = None
</ins><span class="cx"> self.mUseDuration = False
</span><span class="cx"> elif duration is not None:
</span><span class="cx"> self.mDuration = duration
</span><del>- self.mEnd = self.mStart + self.mDuration
</del><ins>+ self.mEnd = None
</ins><span class="cx"> self.mUseDuration = True
</span><span class="cx"> else:
</span><span class="cx"> self.mEnd = self.mStart.duplicate()
</span><del>- self.mDuration = Duration()
</del><ins>+ self.mDuration = None
</ins><span class="cx"> self.mUseDuration = False
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def duplicate(self):
</span><del>- other = Period(start=self.mStart.duplicate(), end=self.mEnd.duplicate())
- other.mUseDuration = self.mUseDuration
</del><ins>+ if self.mUseDuration:
+ other = Period(start=self.mStart.duplicate(), duration=self.mDuration.duplicate())
+ else:
+ other = Period(start=self.mStart.duplicate(), end=self.mEnd.duplicate())
</ins><span class="cx"> return other
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __hash__(self):
</span><del>- return hash((self.mStart, self.mEnd,))
</del><ins>+ return hash((self.mStart, self.getEnd(),))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><span class="lines">@@ -59,7 +61,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __eq__(self, comp):
</span><del>- return self.mStart == comp.mStart and self.mEnd == comp.mEnd
</del><ins>+ return self.mStart == comp.mStart and self.getEnd() == comp.getEnd()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __gt__(self, comp):
</span><span class="lines">@@ -68,7 +70,7 @@
</span><span class="cx">
</span><span class="cx"> def __lt__(self, comp):
</span><span class="cx"> return self.mStart < comp.mStart \
</span><del>- or (self.mStart == comp.mStart) and self.mEnd < comp.mEnd
</del><ins>+ or (self.mStart == comp.mStart) and self.getEnd() < comp.getEnd()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="lines">@@ -79,21 +81,24 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def parse(self, data, fullISO=False):
</span><del>- splits = data.split('/', 1)
- if len(splits) == 2:
- start = splits[0]
- end = splits[1]
</del><ins>+ try:
+ splits = data.split('/', 1)
+ if len(splits) == 2:
+ start = splits[0]
+ end = splits[1]
</ins><span class="cx">
</span><del>- self.mStart.parse(start, fullISO)
- if end[0] == 'P':
- self.mDuration.parse(end)
- self.mUseDuration = True
- self.mEnd = self.mStart + self.mDuration
</del><ins>+ self.mStart.parse(start, fullISO)
+ if end[0] == 'P':
+ self.mDuration = Duration.parseText(end)
+ self.mUseDuration = True
+ self.mEnd = None
+ else:
+ self.mEnd.parse(end, fullISO)
+ self.mUseDuration = False
+ self.mDuration = None
</ins><span class="cx"> else:
</span><del>- self.mEnd.parse(end, fullISO)
- self.mUseDuration = False
- self.mDuration = self.mEnd - self.mStart
- else:
</del><ins>+ raise ValueError
+ except IndexError:
</ins><span class="cx"> raise ValueError
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -146,10 +151,14 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def getEnd(self):
</span><ins>+ if self.mEnd is None:
+ self.mEnd = self.mStart + self.mDuration
</ins><span class="cx"> return self.mEnd
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def getDuration(self):
</span><ins>+ if self.mDuration is None:
+ self.mDuration = self.mEnd - self.mStart
</ins><span class="cx"> return self.mDuration
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -159,11 +168,15 @@
</span><span class="cx">
</span><span class="cx"> def setUseDuration(self, use):
</span><span class="cx"> self.mUseDuration = use
</span><ins>+ if self.mUseDuration and self.mDuration is None:
+ self.getDuration()
+ elif not self.mUseDuration and self.mEnd is None:
+ self.getEnd()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def isDateWithinPeriod(self, dt):
</span><span class="cx"> # Inclusive start, exclusive end
</span><del>- return dt >= self.mStart and dt < self.mEnd
</del><ins>+ return dt >= self.mStart and dt < self.getEnd()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def isDateBeforePeriod(self, dt):
</span><span class="lines">@@ -173,17 +186,17 @@
</span><span class="cx">
</span><span class="cx"> def isDateAfterPeriod(self, dt):
</span><span class="cx"> # Exclusive end
</span><del>- return dt >= self.mEnd
</del><ins>+ return dt >= self.getEnd()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def isPeriodOverlap(self, p):
</span><span class="cx"> # Inclusive start, exclusive end
</span><del>- return not (self.mStart >= p.mEnd or self.mEnd <= p.mStart)
</del><ins>+ return not (self.mStart >= p.getEnd() or self.getEnd() <= p.mStart)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def adjustToUTC(self):
</span><span class="cx"> self.mStart.adjustToUTC()
</span><del>- self.mEnd.adjustToUTC()
</del><ins>+ self.getEnd().adjustToUTC()
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def describeDuration(self):
</span></span></pre></div>
<a id="PyCalendartrunksrcpycalendarteststest_periodpy"></a>
<div class="addfile"><h4>Added: PyCalendar/trunk/src/pycalendar/tests/test_period.py (0 => 14695)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/tests/test_period.py         (rev 0)
+++ PyCalendar/trunk/src/pycalendar/tests/test_period.py        2015-04-22 15:58:34 UTC (rev 14695)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+##
+# 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.duration import Duration
+from pycalendar.period import Period
+import unittest
+
+class TestPeriod(unittest.TestCase):
+
+ test_data = (
+ "20000101T000000Z/20000101T010000Z",
+ "20000101T000000Z/PT1H",
+ )
+
+ def testParseGenerate(self):
+
+ for result in TestPeriod.test_data:
+ period = Period.parseText(result)
+ self.assertEqual(period.getText(), result)
+
+
+ def testParseBad(self):
+
+ test_bad_data = (
+ "",
+ "ABC",
+ "20000101T000000Z",
+ "20000101T000000Z/",
+ "20000101T000000Z/P",
+ "20000101T000000Z/2000",
+ )
+ for data in test_bad_data:
+ self.assertRaises(ValueError, Period.parseText, data)
+
+
+ def testSetUseDuration(self):
+
+ p1 = Period(
+ start=DateTime(2000, 1, 1, 0, 0, 0),
+ end=DateTime(2000, 1, 1, 1, 0, 0),
+ )
+ p1.setUseDuration(True)
+ self.assertTrue(p1.getText(), "20000101T000000/PT1H")
+
+ p2 = Period(
+ start=DateTime(2000, 1, 1, 0, 0, 0),
+ duration=Duration(hours=1),
+ )
+ p2.setUseDuration(False)
+ self.assertTrue(p2.getText(), "20000101T000000/20000101T010000")
</ins></span></pre></div>
<a id="PyCalendartrunksrcpycalendartimezonepy"></a>
<div class="modfile"><h4>Modified: PyCalendar/trunk/src/pycalendar/timezone.py (14694 => 14695)</h4>
<pre class="diff"><span>
<span class="info">--- PyCalendar/trunk/src/pycalendar/timezone.py        2015-04-21 22:54:54 UTC (rev 14694)
+++ PyCalendar/trunk/src/pycalendar/timezone.py        2015-04-22 15:58:34 UTC (rev 14695)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> sDefaultTimezone = None
</span><ins>+ UTCTimezone = None
</ins><span class="cx">
</span><span class="cx"> def __init__(self, utc=None, tzid=None):
</span><span class="cx">
</span><span class="lines">@@ -127,3 +128,4 @@
</span><span class="cx"> return TimezoneDatabase.getTimezoneDescriptor(self.mTimezone, dt)
</span><span class="cx">
</span><span class="cx"> Timezone.sDefaultTimezone = Timezone()
</span><ins>+Timezone.UTCTimezone = Timezone(utc=True)
</ins></span></pre>
</div>
</div>
</body>
</html>