<!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>[14933] CalendarServer/trunk/txdav</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/14933">14933</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-06-30 12:35:01 -0700 (Tue, 30 Jun 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add a test to verify a group removed attendee gets a cancel message. Use mix-in class for tests that need to do iCalendar date-time substitutions.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_queue_schedulingpy">CalendarServer/trunk/txdav/caldav/datastore/test/test_queue_scheduling.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy">CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py</a></li>
<li><a href="#CalendarServertrunktxdavcaldavdatastoretestutilpy">CalendarServer/trunk/txdav/caldav/datastore/test/util.py</a></li>
<li><a href="#CalendarServertrunktxdavcommondatastoretestutilpy">CalendarServer/trunk/txdav/common/datastore/test/util.py</a></li>
<li><a href="#CalendarServertrunktxdavwhotesttest_group_attendeespy">CalendarServer/trunk/txdav/who/test/test_group_attendees.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_queue_schedulingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_queue_scheduling.py (14932 => 14933)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_queue_scheduling.py        2015-06-30 18:57:02 UTC (rev 14932)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_queue_scheduling.py        2015-06-30 19:35:01 UTC (rev 14933)
</span><span class="lines">@@ -19,11 +19,10 @@
</span><span class="cx"> from twext.python.clsprop import classproperty
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from txdav.caldav.datastore.scheduling.work import ScheduleWorkMixin
</span><del>-from txdav.caldav.datastore.test.util import CommonStoreTests
-from txdav.common.datastore.test.util import componentUpdate
-from twistedcaldav.ical import normalize_iCalStr
</del><ins>+from txdav.caldav.datastore.test.util import CommonStoreTests, \
+    DateTimeSubstitutionsMixin
</ins><span class="cx"> 
</span><del>-class BaseQueueSchedulingTests(CommonStoreTests):
</del><ins>+class BaseQueueSchedulingTests(CommonStoreTests, DateTimeSubstitutionsMixin):
</ins><span class="cx"> 
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Test store-based calendar sharing.
</span><span class="lines">@@ -41,7 +40,9 @@
</span><span class="cx">         self.patch(config.Scheduling.Options.WorkQueues, &quot;AttendeeRefreshBatchDelaySeconds&quot;, 1)
</span><span class="cx">         self.patch(config.Scheduling.Options.WorkQueues, &quot;AttendeeRefreshBatchIntervalSeconds&quot;, 1)
</span><span class="cx"> 
</span><ins>+        self.setupDateTimeValues()
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty(cache=False)
</span><span class="cx">     def requirements(cls): #@NoSelf
</span><span class="cx">         return {
</span><span class="lines">@@ -87,7 +88,7 @@
</span><span class="cx">         self.assertEqual(len(objs), 1)
</span><span class="cx"> 
</span><span class="cx">         caldata = yield objs[0].componentForUser()
</span><del>-        self.assertEqual(normalize_iCalStr(caldata), normalize_iCalStr(componentUpdate(data)))
</del><ins>+        self.assertEqualCalendarData(caldata, data.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -104,7 +105,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01@example.com
</span><span class="cx"> ATTENDEE:mailto:user02@example.com
</span><span class="lines">@@ -120,7 +121,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user02
</span><span class="lines">@@ -137,7 +138,7 @@
</span><span class="cx"> METHOD:REQUEST
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="lines">@@ -153,7 +154,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="lines">@@ -170,7 +171,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user02
</span><span class="lines">@@ -186,7 +187,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;PARTSTAT=ACCEPTED;SCHEDULE-STATUS=2.0:urn:x-uid:user02
</span><span class="lines">@@ -203,7 +204,7 @@
</span><span class="cx"> METHOD:REPLY
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user02
</span><span class="cx"> DTSTAMP:20051222T210507Z
</span><span class="lines">@@ -219,7 +220,7 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:12345-67890
</span><del>-DTSTART:{now}T000000Z
</del><ins>+DTSTART:{nowDate}T000000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user02
</span><span class="lines">@@ -232,7 +233,7 @@
</span><span class="cx"> 
</span><span class="cx">         waitForWork = ScheduleWorkMixin.allDone()
</span><span class="cx">         calendar = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><del>-        yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, componentUpdate(data1))
</del><ins>+        yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, data1.format(**self.dtsubs))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         yield waitForWork
</span><span class="lines">@@ -244,7 +245,7 @@
</span><span class="cx"> 
</span><span class="cx">         waitForWork = ScheduleWorkMixin.allDone()
</span><span class="cx">         cobj = yield self._getOneResource(&quot;user02&quot;, &quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(componentUpdate(data5))
</del><ins>+        yield cobj.setComponent(data5.format(**self.dtsubs))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         yield waitForWork
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretesttest_sqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py (14932 => 14933)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2015-06-30 18:57:02 UTC (rev 14932)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_sql.py        2015-06-30 19:35:01 UTC (rev 14933)
</span><span class="lines">@@ -60,6 +60,7 @@
</span><span class="cx"> from txdav.caldav.datastore.test.common import CommonTests as CalendarCommonTests, \
</span><span class="cx">     test_event_text, cal1Root
</span><span class="cx"> from txdav.caldav.datastore.test.test_file import setUpCalendarStore
</span><ins>+from txdav.caldav.datastore.test.util import DateTimeSubstitutionsMixin
</ins><span class="cx"> from txdav.common.datastore.test.util import populateCalendarsFrom, \
</span><span class="cx">     CommonCommonTests, updateToCurrentYear
</span><span class="cx"> from txdav.caldav.datastore.util import _migrateCalendar, migrateHome
</span><span class="lines">@@ -3162,7 +3163,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class CalendarObjectSplitting(CommonCommonTests, unittest.TestCase):
</del><ins>+class CalendarObjectSplitting(CommonCommonTests, DateTimeSubstitutionsMixin, unittest.TestCase):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalendarObject splitting tests
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -3179,71 +3180,8 @@
</span><span class="cx">             self.assertNotEqual(home_uid, None)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><del>-        self.subs = {}
</del><ins>+        self.setupDateTimeValues()
</ins><span class="cx"> 
</span><del>-        self.now = DateTime.getNowUTC()
-        self.now.setHHMMSS(0, 0, 0)
-        self.nowDate = self.now.duplicate()
-        self.nowDate.setDateOnly(True)
-        self.nowFloating = self.now.duplicate()
-        self.nowFloating.setTimezoneID(None)
-
-        self.subs[&quot;now&quot;] = self.now
-        self.subs[&quot;nowDate&quot;] = self.nowDate
-        self.subs[&quot;nowFloating&quot;] = self.nowFloating
-
-        for i in range(30):
-            attrname = &quot;now_back%s&quot; % (i + 1,)
-            setattr(self, attrname, self.now.duplicate())
-            getattr(self, attrname).offsetDay(-(i + 1))
-            self.subs[attrname] = getattr(self, attrname)
-
-            attrname_12h = &quot;now_back%s_12h&quot; % (i + 1,)
-            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
-            getattr(self, attrname_12h).offsetHours(12)
-            self.subs[attrname_12h] = getattr(self, attrname_12h)
-
-            attrname_1 = &quot;now_back%s_1&quot; % (i + 1,)
-            setattr(self, attrname_1, getattr(self, attrname).duplicate())
-            getattr(self, attrname_1).offsetSeconds(-1)
-            self.subs[attrname_1] = getattr(self, attrname_1)
-
-            attrname = &quot;nowDate_back%s&quot; % (i + 1,)
-            setattr(self, attrname, self.nowDate.duplicate())
-            getattr(self, attrname).offsetDay(-(i + 1))
-            self.subs[attrname] = getattr(self, attrname)
-
-            attrname = &quot;nowFloating_back%s&quot; % (i + 1,)
-            setattr(self, attrname, self.nowFloating.duplicate())
-            getattr(self, attrname).offsetDay(-(i + 1))
-            self.subs[attrname] = getattr(self, attrname)
-
-            attrname_1 = &quot;nowFloating_back%s_1&quot; % (i + 1,)
-            setattr(self, attrname_1, getattr(self, attrname).duplicate())
-            getattr(self, attrname_1).offsetSeconds(-1)
-            self.subs[attrname_1] = getattr(self, attrname_1)
-
-        for i in range(30):
-            attrname = &quot;now_fwd%s&quot; % (i + 1,)
-            setattr(self, attrname, self.now.duplicate())
-            getattr(self, attrname).offsetDay(i + 1)
-            self.subs[attrname] = getattr(self, attrname)
-
-            attrname_12h = &quot;now_fwd%s_12h&quot; % (i + 1,)
-            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
-            getattr(self, attrname_12h).offsetHours(12)
-            self.subs[attrname_12h] = getattr(self, attrname_12h)
-
-            attrname = &quot;nowDate_fwd%s&quot; % (i + 1,)
-            setattr(self, attrname, self.nowDate.duplicate())
-            getattr(self, attrname).offsetDay(i + 1)
-            self.subs[attrname] = getattr(self, attrname)
-
-            attrname = &quot;nowFloating_fwd%s&quot; % (i + 1,)
-            setattr(self, attrname, self.nowFloating.duplicate())
-            getattr(self, attrname).offsetDay(i + 1)
-            self.subs[attrname] = getattr(self, attrname)
-
</del><span class="cx">         self.patch(config, &quot;MaxAllowedInstances&quot;, 500)
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -3452,7 +3390,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -3476,7 +3414,7 @@
</span><span class="cx">         ical_future, ical_past, pastUID, relID, _ignore_new_name = yield self._splitDetails(&quot;user01&quot;)
</span><span class="cx"> 
</span><span class="cx">         title = &quot;temp&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = pastUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -3665,7 +3603,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -3689,7 +3627,7 @@
</span><span class="cx">         ical_future, ical_past, pastUID, relID, _ignore_new_name = yield self._splitDetails(&quot;user01&quot;)
</span><span class="cx"> 
</span><span class="cx">         title = &quot;temp&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = pastUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s %s&quot; % (title, diff_iCalStrs(ical_future, data_future % relsubs)))
</span><span class="lines">@@ -3874,7 +3812,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -3898,7 +3836,7 @@
</span><span class="cx">         ical_future, ical_past, pastUID, relID, _ignore_new_name = yield self._splitDetails(&quot;user01&quot;)
</span><span class="cx"> 
</span><span class="cx">         title = &quot;temp&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = pastUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s %s&quot; % (title, diff_iCalStrs(ical_future, data_future % relsubs)))
</span><span class="lines">@@ -4324,7 +4262,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertTrue(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -4353,7 +4291,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = pastUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -4486,7 +4424,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertTrue(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -4708,7 +4646,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -4720,16 +4658,16 @@
</span><span class="cx">         cobj = cobjs[0]
</span><span class="cx">         cname2 = cobj.name()
</span><span class="cx">         ical = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_2) % self.subs, &quot;Failed 2&quot;)
-        yield cobj.setComponent(Component.fromString(data_2_update % self.subs))
</del><ins>+        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_2) % self.dtsubs, &quot;Failed 2&quot;)
+        yield cobj.setComponent(Component.fromString(data_2_update % self.dtsubs))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         ical = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_1) % self.subs, &quot;Failed 2&quot;)
</del><ins>+        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_1) % self.dtsubs, &quot;Failed 2&quot;)
</ins><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=cname2, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         ical = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_2_changed) % self.subs, &quot;Failed 2&quot;)
</del><ins>+        self.assertEqual(normalize_iCalStr(ical), normalize_iCalStr(data_2_changed) % self.dtsubs, &quot;Failed 2&quot;)
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -4794,7 +4732,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -5090,7 +5028,7 @@
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Create initial non-split event
</span><del>-        cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, Component.fromString(data_1 % self.subs))
</del><ins>+        cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, Component.fromString(data_1 % self.dtsubs))
</ins><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -5107,7 +5045,7 @@
</span><span class="cx">         self.assertEqual(attachment.parameterValue(&quot;MANAGED-ID&quot;), mid)
</span><span class="cx">         self.assertEqual(attachment.value(), location)
</span><span class="cx"> 
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;mid&quot;] = mid
</span><span class="cx">         relsubs[&quot;att_uri&quot;] = location
</span><span class="cx">         relsubs[&quot;dtstamp&quot;] = str(ical.masterComponent().propertyValue(&quot;DTSTAMP&quot;))
</span><span class="lines">@@ -5447,7 +5385,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -5459,7 +5397,7 @@
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         processor.recipient_calendar_resource = cobj
</span><span class="cx">         processor.recipient_calendar = (yield cobj.componentForUser(&quot;user01&quot;))
</span><del>-        processor.message = Component.fromString(itip1 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip1 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;REQUEST&quot;
</span><span class="lines">@@ -5470,7 +5408,7 @@
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         new_names = []
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         @inlineCallbacks
</span><span class="cx">         def _verify_state():
</span><span class="lines">@@ -5599,7 +5537,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -5611,7 +5549,7 @@
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         processor.recipient_calendar_resource = cobj
</span><span class="cx">         processor.recipient_calendar = (yield cobj.componentForUser(&quot;user01&quot;))
</span><del>-        processor.message = Component.fromString(itip1 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip1 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;CANCEL&quot;
</span><span class="lines">@@ -5622,7 +5560,7 @@
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Get user01 data
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><span class="lines">@@ -5720,7 +5658,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -5732,7 +5670,7 @@
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         processor.recipient_calendar_resource = cobj
</span><span class="cx">         processor.recipient_calendar = (yield cobj.componentForUser(&quot;user01&quot;))
</span><del>-        processor.message = Component.fromString(itip1 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip1 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;REQUEST&quot;
</span><span class="lines">@@ -5743,7 +5681,7 @@
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Get user01 data
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><span class="lines">@@ -5893,7 +5831,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -5905,7 +5843,7 @@
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         processor.recipient_calendar_resource = cobj
</span><span class="cx">         processor.recipient_calendar = (yield cobj.componentForUser(&quot;user01&quot;))
</span><del>-        processor.message = Component.fromString(itip1 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip1 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;REQUEST&quot;
</span><span class="lines">@@ -5917,7 +5855,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Get user01 data
</span><span class="cx">         ical_future, ical_past, pastUID, relID, _ignore_new_name = yield self._splitDetails(&quot;user01&quot;)
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = pastUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx"> 
</span><span class="lines">@@ -6096,7 +6034,7 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -6117,7 +6055,7 @@
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         processor.recipient_calendar_resource = cobj
</span><span class="cx">         processor.recipient_calendar = (yield cobj.componentForUser(&quot;user01&quot;))
</span><del>-        processor.message = Component.fromString(itip1 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip1 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;REQUEST&quot;
</span><span class="lines">@@ -6136,7 +6074,7 @@
</span><span class="cx"> 
</span><span class="cx">         processor.recipient_calendar_resource = None
</span><span class="cx">         processor.recipient_calendar = None
</span><del>-        processor.message = Component.fromString(itip2 % self.subs)
</del><ins>+        processor.message = Component.fromString(itip2 % self.dtsubs)
</ins><span class="cx">         processor.originator = RemoteCalendarUser(&quot;mailto:cuser01@example.org&quot;)
</span><span class="cx">         processor.recipient = LocalCalendarUser(&quot;urn:x-uid:user01&quot;, None)
</span><span class="cx">         processor.method = &quot;REQUEST&quot;
</span><span class="lines">@@ -6497,7 +6435,7 @@
</span><span class="cx">                     responses.add(recipient, responsecode.NOT_FOUND, reqstatus=iTIPRequestStatus.INVALID_CALENDAR_USER)
</span><span class="cx">             return succeed(responses)
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertTrue(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -6538,7 +6476,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s\n%s&quot; % (title, diff_iCalStrs(ical_future, data_future % relsubs),))
</span><span class="lines">@@ -6894,7 +6832,7 @@
</span><span class="cx">         # Create one event without active split
</span><span class="cx">         self.patch(config.Scheduling.Options.Splitting, &quot;Enabled&quot;, False)
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        component = Component.fromString(data_init % self.subs)
</del><ins>+        component = Component.fromString(data_init % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -6929,7 +6867,7 @@
</span><span class="cx">             return oldScheduling(self, do_smart_merge, split_details)
</span><span class="cx">         self.patch(ImplicitScheduler, &quot;doImplicitScheduling&quot;, newScheduling)
</span><span class="cx"> 
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         yield self.failUnlessFailure(cobj.setComponent(component), AlreadyFinishedError)
</span><span class="cx">         self.assertTrue(self.transactionUnderTest().timedout)
</span><span class="cx"> 
</span><span class="lines">@@ -6973,7 +6911,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -7235,7 +7173,7 @@
</span><span class="cx">         # Create one event without active split
</span><span class="cx">         self.patch(config.Scheduling.Options.Splitting, &quot;Enabled&quot;, False)
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7278,7 +7216,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -7578,7 +7516,7 @@
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Create it
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7706,7 +7644,7 @@
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         # Create it
</span><del>-        component = Component.fromString(data % self.subs)
</del><ins>+        component = Component.fromString(data % self.dtsubs)
</ins><span class="cx">         cobj = yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, component)
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7732,7 +7670,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs))
</del><ins>+        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs))
</ins><span class="cx">         oldname = oldobj.name()
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7769,7 +7707,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -7808,7 +7746,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back15_12h)s&quot; % self.subs))
</del><ins>+        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back15_12h)s&quot; % self.dtsubs))
</ins><span class="cx">         oldname = oldobj.name()
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7845,7 +7783,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -7884,7 +7822,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs))
</del><ins>+        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs))
</ins><span class="cx">         oldname = oldobj.name()
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -7921,7 +7859,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -7940,7 +7878,7 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -7955,7 +7893,7 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_back30)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_back30)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -7970,7 +7908,7 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_fwd25)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(now_fwd25)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -7984,7 +7922,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs), pastUID=pastUID)
</del><ins>+        oldobj = yield cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs), pastUID=pastUID)
</ins><span class="cx">         oldname = oldobj.name()
</span><span class="cx">         self.assertFalse(hasattr(cobj, &quot;_workItems&quot;))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -8023,7 +7961,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Verify user01 data
</span><span class="cx">         title = &quot;user01&quot;
</span><del>-        relsubs = dict(self.subs)
</del><ins>+        relsubs = dict(self.dtsubs)
</ins><span class="cx">         relsubs[&quot;uid&quot;] = newUID
</span><span class="cx">         relsubs[&quot;relID&quot;] = relID
</span><span class="cx">         self.assertEqual(normalize_iCalStr(ical_future), normalize_iCalStr(data_future) % relsubs, &quot;Failed future: %s&quot; % (title,))
</span><span class="lines">@@ -8063,7 +8001,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs), pastUID=&quot;12345-67890&quot;), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs), pastUID=&quot;12345-67890&quot;), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -8093,13 +8031,13 @@
</span><span class="cx">         yield self._setupSplitAt()
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        component = Component.fromString(data_existing % self.subs)
</del><ins>+        component = Component.fromString(data_existing % self.dtsubs)
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data2.ics&quot;, component)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Update it
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.subs), pastUID=&quot;12345-67890-existing&quot;), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now_back14)s&quot; % self.dtsubs), pastUID=&quot;12345-67890-existing&quot;), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -8114,10 +8052,10 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(nowDate)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(nowDate)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx">         # DTSTART DATE-TIME UTC/rid DATE-TIME floating
</span><del>-        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(nowFloating)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobjs[0].splitAt(DateTime.parseText(&quot;%(nowFloating)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx">         data_floating = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -8137,20 +8075,20 @@
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        component = Component.fromString(data_floating % self.subs)
</del><ins>+        component = Component.fromString(data_floating % self.dtsubs)
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data2.ics&quot;, component)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # DTSTART DATE/rid DATE-TIME floating
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data2.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><del>-        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(nowFloating)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(nowFloating)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx">         # DTSTART DATE/rid DATE-TIME UTC
</span><del>-        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now)s&quot; % self.subs)), InvalidSplit)
</del><ins>+        yield self.failUnlessFailure(cobj.splitAt(DateTime.parseText(&quot;%(now)s&quot; % self.dtsubs)), InvalidSplit)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class TimeRangeUpdateOptimization(CommonCommonTests, unittest.TestCase):
</del><ins>+class TimeRangeUpdateOptimization(CommonCommonTests, DateTimeSubstitutionsMixin, unittest.TestCase):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalendarObject time range optimization tests.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -8162,7 +8100,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8177,7 +8115,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8192,7 +8130,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T130000Z
</del><ins>+DTSTART:{nowDate}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8207,7 +8145,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8223,7 +8161,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> STATUS:CANCELLED
</span><span class="lines">@@ -8239,7 +8177,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8255,7 +8193,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8271,7 +8209,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8287,12 +8225,12 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="cx"> RRULE:FREQ=DAILY
</span><del>-EXDATE:{now}T120000Z
</del><ins>+EXDATE:{nowDate}T120000Z
</ins><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="lines">@@ -8304,12 +8242,12 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="cx"> RRULE:FREQ=DAILY
</span><del>-RDATE:{now}T150000Z
</del><ins>+RDATE:{nowDate}T150000Z
</ins><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="lines">@@ -8321,12 +8259,7 @@
</span><span class="cx">         yield self.buildStoreAndDirectory()
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><del>-        self.now = DateTime.getNowUTC()
-        self.now.setDateOnly(True)
-        self.now1 = self.now.duplicate()
-        self.now1.offsetDay(1)
-        self.now2 = self.now.duplicate()
-        self.now2.offsetDay(2)
</del><ins>+        self.setupDateTimeValues()
</ins><span class="cx"> 
</span><span class="cx">         self.trcount = 0
</span><span class="cx">         base_addInstances = CalendarObject._addInstances
</span><span class="lines">@@ -8370,7 +8303,7 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="lines">@@ -8384,14 +8317,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT does not cause T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT2.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT2.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="lines">@@ -8407,14 +8340,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT does cause T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT2.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT2.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8428,14 +8361,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT3.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT3.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8449,14 +8382,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT4.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT4.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8470,14 +8403,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT5.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT5.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8491,14 +8424,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT6.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT6.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8512,14 +8445,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT8.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT8.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8533,14 +8466,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT9.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT9.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8554,14 +8487,14 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest()
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.EVENT7.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 1)
</span><span class="cx"> 
</span><span class="cx">         # Second PUT causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest()
</span><del>-        yield cobj.setComponent(Component.fromString(self.EVENT10.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.EVENT10.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 2)
</span><span class="lines">@@ -8574,7 +8507,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8592,7 +8525,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8610,7 +8543,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8628,7 +8561,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T140000Z
</del><ins>+DTSTART:{nowDate}T140000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8650,7 +8583,7 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 3)
</span><span class="lines">@@ -8659,21 +8592,21 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;calendar&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield cobjs[0].setComponent(Component.fromString(self.INVITE2.format(now=self.now.getText())))
</del><ins>+        yield cobjs[0].setComponent(Component.fromString(self.INVITE2.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 5)
</span><span class="cx"> 
</span><span class="cx">         # Organizer summary change does not cause T-R change (except for inbox item)
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE3.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE3.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 6)
</span><span class="cx"> 
</span><span class="cx">         # Organizer dtstart change causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE4.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE4.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 9)
</span><span class="lines">@@ -8692,7 +8625,7 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE1.format(now=self.now.getText())))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 3)
</span><span class="lines">@@ -8701,21 +8634,21 @@
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;calendar&quot;)
</span><span class="cx">         cobjs = yield cal.calendarObjects()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><del>-        yield cobjs[0].setComponent(Component.fromString(self.INVITE2.format(now=self.now.getText())))
</del><ins>+        yield cobjs[0].setComponent(Component.fromString(self.INVITE2.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 5)
</span><span class="cx"> 
</span><span class="cx">         # Organizer summary change causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE3.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE3.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 8)
</span><span class="cx"> 
</span><span class="cx">         # Organizer dtstart change causes T-R change
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE4.format(now=self.now.getText())))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE4.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         self.assertEqual(self.trcount, 11)
</span><span class="lines">@@ -8728,7 +8661,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8739,8 +8672,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now1}T120000Z
-DTSTART:{now1}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd1}T120000Z
+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8758,8 +8691,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now1}T120000Z
-DTSTART:{now1}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd1}T120000Z
+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8777,7 +8710,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8788,8 +8721,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now1}T120000Z
-DTSTART:{now1}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd1}T120000Z
+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8800,8 +8733,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now2}T120000Z
-DTSTART:{now2}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd2}T120000Z
+DTSTART:{nowDate_fwd2}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now2
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8819,7 +8752,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now}T120000Z
</del><ins>+DTSTART:{nowDate}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8830,8 +8763,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now1}T120000Z
-DTSTART:{now1}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd1}T120000Z
+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8841,8 +8774,8 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> CREATED:20100203T013849Z
</span><span class="cx"> UID:uid1
</span><del>-RECURRENCE-ID:{now2}T120000Z
-DTSTART:{now2}T120000Z
</del><ins>+RECURRENCE-ID:{nowDate_fwd2}T120000Z
+DTSTART:{nowDate_fwd2}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event now2
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8866,11 +8799,7 @@
</span><span class="cx"> 
</span><span class="cx">         # First PUT causes T-R change
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><del>-        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE_OVERRIDE1.format(
-            now=self.now.getText(),
-            now1=self.now1.getText(),
-            now2=self.now2.getText(),
-        )))
</del><ins>+        yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(self.INVITE_OVERRIDE1.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Wait for it to complete
</span><span class="lines">@@ -8880,11 +8809,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Organizer adds attendee to override causes T-R change (except for their item)
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE3.format(
-            now=self.now.getText(),
-            now1=self.now1.getText(),
-            now2=self.now2.getText(),
-        )))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE3.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Wait for it to complete
</span><span class="lines">@@ -8894,11 +8819,7 @@
</span><span class="cx"> 
</span><span class="cx">         # Organizer removes attendee from override causes T-R change (except for their item)
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(home=&quot;user01&quot;, calendar_name=&quot;calendar&quot;)
</span><del>-        yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE4.format(
-            now=self.now.getText(),
-            now1=self.now1.getText(),
-            now2=self.now2.getText(),
-        )))
</del><ins>+        yield cobj.setComponent(Component.fromString(self.INVITE_OVERRIDE4.format(**self.dtsubs)))
</ins><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         # Wait for it to complete
</span><span class="lines">@@ -8908,7 +8829,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class GroupExpand(CommonCommonTests, unittest.TestCase):
</del><ins>+class GroupExpand(CommonCommonTests, DateTimeSubstitutionsMixin, unittest.TestCase):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     CalendarObject group attendee expansion.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -8926,26 +8847,11 @@
</span><span class="cx"> 
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><del>-        now = DateTime.getNowUTC()
-        now.setDateOnly(True)
-        past1 = now.duplicate()
-        past1.offsetDay(-1)
-        past2 = now.duplicate()
-        past2.offsetDay(-2)
-        past400 = now.duplicate()
</del><ins>+        self.setupDateTimeValues()
+
+        past400 = self.nowDate.duplicate()
</ins><span class="cx">         past400.offsetDay(-400)
</span><del>-        now1 = now.duplicate()
-        now1.offsetDay(1)
-        now2 = now.duplicate()
-        now2.offsetDay(2)
-        self.subs = {
-            &quot;now&quot;: now,
-            &quot;past1&quot;: past1,
-            &quot;past2&quot;: past2,
-            &quot;past400&quot;: past400,
-            &quot;now1&quot;: now1,
-            &quot;now2&quot;: now2,
-        }
</del><ins>+        self.dtsubs[&quot;nowDate_back400&quot;] = past400
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -8984,7 +8890,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -8993,7 +8899,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9002,7 +8908,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9011,7 +8917,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9038,7 +8944,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9046,7 +8952,7 @@
</span><span class="cx"> ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01@example.com
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9054,7 +8960,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9063,7 +8969,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9072,7 +8978,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9082,8 +8988,17 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><ins>+        # Group user has no data
+        cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;calendar&quot;)
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 0)
+        cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;inbox&quot;)
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 0)
+        yield self.commit()
+
</ins><span class="cx">         # PUT does not cause expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="cx">         yield cal.createObjectResourceWithName(&quot;1.ics&quot;, Component.fromString(event1))
</span><span class="lines">@@ -9106,7 +9021,18 @@
</span><span class="cx">         links = yield calobj.groupEventLinks()
</span><span class="cx">         self.assertEqual(len(links), 1)
</span><span class="cx"> 
</span><ins>+        # Group user has invite data
+        cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;calendar&quot;)
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        cal = yield self.calendarUnderTest(home=&quot;user02&quot;, name=&quot;inbox&quot;)
+        cobjs = yield cal.calendarObjects()
+        self.assertEqual(len(cobjs), 1)
+        comp = yield cobjs[0].componentForUser()
+        self.assertTrue(&quot;METHOD:REQUEST&quot; in str(comp))
+        yield self.commit()
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_expand_update_existing(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -9119,7 +9045,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9128,7 +9054,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9137,7 +9063,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9147,7 +9073,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event3 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9156,7 +9082,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T130000Z
</del><ins>+DTSTART:{nowDate_fwd1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9166,7 +9092,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9175,7 +9101,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T130000Z
</del><ins>+DTSTART:{nowDate_fwd1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9185,7 +9111,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9231,7 +9157,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9241,7 +9167,7 @@
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9250,7 +9176,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9260,7 +9186,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9287,7 +9213,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9296,7 +9222,7 @@
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9304,7 +9230,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9314,7 +9240,7 @@
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9323,7 +9249,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9334,7 +9260,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT does not cause expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9371,7 +9297,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9381,7 +9307,7 @@
</span><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9390,7 +9316,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T120000Z
</del><ins>+DTSTART:{nowDate_fwd1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9401,7 +9327,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event3 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9410,7 +9336,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T130000Z
</del><ins>+DTSTART:{nowDate_fwd1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9421,7 +9347,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9430,7 +9356,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{now1}T130000Z
</del><ins>+DTSTART:{nowDate_fwd1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9441,7 +9367,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9487,7 +9413,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9496,7 +9422,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9505,7 +9431,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9514,7 +9440,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9541,7 +9467,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9549,7 +9475,7 @@
</span><span class="cx"> ATTENDEE;PARTSTAT=ACCEPTED:mailto:user01@example.com
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9557,7 +9483,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9566,7 +9492,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9575,7 +9501,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9585,7 +9511,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT does not cause expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9622,7 +9548,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9631,7 +9557,7 @@
</span><span class="cx"> ATTENDEE:urn:x-uid:group01
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event2 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9640,7 +9566,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9650,7 +9576,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         event3 = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9659,7 +9585,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T130000Z
</del><ins>+DTSTART:{nowDate_back1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9669,7 +9595,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9678,7 +9604,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T130000Z
</del><ins>+DTSTART:{nowDate_back1}T130000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9688,7 +9614,7 @@
</span><span class="cx"> SUMMARY:New Event #2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9735,7 +9661,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9745,7 +9671,7 @@
</span><span class="cx"> RRULE:FREQ=YEARLY;INTERVAL=2
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9754,7 +9680,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past1}T120000Z
</del><ins>+DTSTART:{nowDate_back1}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9764,7 +9690,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span><span class="lines">@@ -9792,7 +9718,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><del>-DTSTART:{past400}T120000Z
</del><ins>+DTSTART:{nowDate_back400}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><span class="lines">@@ -9802,7 +9728,7 @@
</span><span class="cx"> RRULE:FREQ=YEARLY;INTERVAL=4
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         result = &quot;&quot;&quot;BEGIN:VCALENDAR
</span><span class="cx"> VERSION:2.0
</span><span class="lines">@@ -9811,7 +9737,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:uid1
</span><span class="cx"> DTSTAMP:20100203T013909Z
</span><del>-DTSTART:{past400}T120000Z
</del><ins>+DTSTART:{nowDate_back400}T120000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;PARTSTAT=ACCEPTED:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -9821,7 +9747,7 @@
</span><span class="cx"> SUMMARY:New Event
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><del>-&quot;&quot;&quot;.format(**self.subs)
</del><ins>+&quot;&quot;&quot;.format(**self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">         # PUT causes expansion
</span><span class="cx">         cal = yield self.calendarUnderTest(home=&quot;user01&quot;, name=&quot;calendar&quot;)
</span></span></pre></div>
<a id="CalendarServertrunktxdavcaldavdatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/caldav/datastore/test/util.py (14932 => 14933)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/caldav/datastore/test/util.py        2015-06-30 18:57:02 UTC (rev 14932)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/util.py        2015-06-30 19:35:01 UTC (rev 14933)
</span><span class="lines">@@ -15,8 +15,10 @@
</span><span class="cx"> # limitations under the License.
</span><span class="cx"> ##
</span><span class="cx"> from twisted.trial.unittest import TestCase
</span><ins>+from twisted.internet.defer import inlineCallbacks
</ins><span class="cx"> from twext.python.clsprop import classproperty
</span><del>-from twisted.internet.defer import inlineCallbacks
</del><ins>+from twistedcaldav.ical import Component, normalize_iCalStr, diff_iCalStrs
+from pycalendar.datetime import DateTime
</ins><span class="cx"> 
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> Store test utility functions
</span><span class="lines">@@ -70,3 +72,96 @@
</span><span class="cx">                 },
</span><span class="cx">             },
</span><span class="cx">         }
</span><ins>+
+
+
+class DateTimeSubstitutionsMixin(object):
+    &quot;&quot;&quot;
+    Mix-in class for tests that defines a set of str.format() substitutions for date-time values
+    relative to the current time. This allows tests to always use relative-to-now values rather
+    than fixed values which may become in valid in the future (e.g., a test that needs an event
+    in the future and uses 2017 works fine up until 2017 and then starts to fail.
+    &quot;&quot;&quot;
+
+    def setupDateTimeValues(self):
+
+        self.dtsubs = {}
+
+        # Set of &quot;now&quot; values that are directly accessible
+        self.now = DateTime.getNowUTC()
+        self.now.setHHMMSS(0, 0, 0)
+        self.now12 = DateTime.getNowUTC()
+        self.now12.setHHMMSS(12, 0, 0)
+        self.nowDate = self.now.duplicate()
+        self.nowDate.setDateOnly(True)
+        self.nowFloating = self.now.duplicate()
+        self.nowFloating.setTimezoneID(None)
+
+        self.dtsubs[&quot;now&quot;] = self.now
+        self.dtsubs[&quot;now12&quot;] = self.now12
+        self.dtsubs[&quot;nowDate&quot;] = self.nowDate
+        self.dtsubs[&quot;nowFloating&quot;] = self.nowFloating
+
+        # Values going 30 days back from now
+        for i in range(30):
+            attrname = &quot;now_back%s&quot; % (i + 1,)
+            setattr(self, attrname, self.now.duplicate())
+            getattr(self, attrname).offsetDay(-(i + 1))
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+            attrname_12h = &quot;now_back%s_12h&quot; % (i + 1,)
+            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
+            getattr(self, attrname_12h).offsetHours(12)
+            self.dtsubs[attrname_12h] = getattr(self, attrname_12h)
+
+            attrname_1 = &quot;now_back%s_1&quot; % (i + 1,)
+            setattr(self, attrname_1, getattr(self, attrname).duplicate())
+            getattr(self, attrname_1).offsetSeconds(-1)
+            self.dtsubs[attrname_1] = getattr(self, attrname_1)
+
+            attrname = &quot;nowDate_back%s&quot; % (i + 1,)
+            setattr(self, attrname, self.nowDate.duplicate())
+            getattr(self, attrname).offsetDay(-(i + 1))
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+            attrname = &quot;nowFloating_back%s&quot; % (i + 1,)
+            setattr(self, attrname, self.nowFloating.duplicate())
+            getattr(self, attrname).offsetDay(-(i + 1))
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+            attrname_1 = &quot;nowFloating_back%s_1&quot; % (i + 1,)
+            setattr(self, attrname_1, getattr(self, attrname).duplicate())
+            getattr(self, attrname_1).offsetSeconds(-1)
+            self.dtsubs[attrname_1] = getattr(self, attrname_1)
+
+        # Values going 30 days forward from now
+        for i in range(30):
+            attrname = &quot;now_fwd%s&quot; % (i + 1,)
+            setattr(self, attrname, self.now.duplicate())
+            getattr(self, attrname).offsetDay(i + 1)
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+            attrname_12h = &quot;now_fwd%s_12h&quot; % (i + 1,)
+            setattr(self, attrname_12h, getattr(self, attrname).duplicate())
+            getattr(self, attrname_12h).offsetHours(12)
+            self.dtsubs[attrname_12h] = getattr(self, attrname_12h)
+
+            attrname = &quot;nowDate_fwd%s&quot; % (i + 1,)
+            setattr(self, attrname, self.nowDate.duplicate())
+            getattr(self, attrname).offsetDay(i + 1)
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+            attrname = &quot;nowFloating_fwd%s&quot; % (i + 1,)
+            setattr(self, attrname, self.nowFloating.duplicate())
+            getattr(self, attrname).offsetDay(i + 1)
+            self.dtsubs[attrname] = getattr(self, attrname)
+
+
+    def assertEqualCalendarData(self, cal1, cal2):
+        if isinstance(cal1, str):
+            cal1 = Component.fromString(cal1)
+        if isinstance(cal2, str):
+            cal2 = Component.fromString(cal2)
+        ncal1 = normalize_iCalStr(cal1)
+        ncal2 = normalize_iCalStr(cal2)
+        self.assertEqual(ncal1, ncal2, msg=diff_iCalStrs(ncal1, ncal2))
</ins></span></pre></div>
<a id="CalendarServertrunktxdavcommondatastoretestutilpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py (14932 => 14933)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/common/datastore/test/util.py        2015-06-30 18:57:02 UTC (rev 14932)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py        2015-06-30 19:35:01 UTC (rev 14933)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav import ical
</span><span class="cx"> from twistedcaldav.config import config, ConfigDict
</span><del>-from twistedcaldav.ical import Component as VComponent, Component
</del><ins>+from twistedcaldav.ical import Component as VComponent
</ins><span class="cx"> from twistedcaldav.stdconfig import DEFAULT_CONFIG
</span><span class="cx"> from twistedcaldav.vcard import Component as ABComponent
</span><span class="cx"> 
</span><span class="lines">@@ -553,36 +553,7 @@
</span><span class="cx">     return data % {&quot;now&quot;: nowYear}
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-relativeDateSubstitutions = {}
</del><span class="cx"> 
</span><del>-
-def componentUpdate(data):
-    &quot;&quot;&quot;
-    Update the supplied iCalendar data so that all dates are updated to the
-    current year.
-    &quot;&quot;&quot;
-
-    if len(relativeDateSubstitutions) == 0:
-        now = DateTime.getToday()
-
-        relativeDateSubstitutions[&quot;now&quot;] = now
-
-        for i in range(30):
-            attrname = &quot;now_back%s&quot; % (i + 1,)
-            dt = now.duplicate()
-            dt.offsetDay(-(i + 1))
-            relativeDateSubstitutions[attrname] = dt
-
-        for i in range(30):
-            attrname = &quot;now_fwd%s&quot; % (i + 1,)
-            dt = now.duplicate()
-            dt.offsetDay(i + 1)
-            relativeDateSubstitutions[attrname] = dt
-
-    return Component.fromString(data.format(**relativeDateSubstitutions))
-
-
-
</del><span class="cx"> @inlineCallbacks
</span><span class="cx"> def resetCalendarMD5s(md5s, store):
</span><span class="cx">     &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktxdavwhotesttest_group_attendeespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txdav/who/test/test_group_attendees.py (14932 => 14933)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/txdav/who/test/test_group_attendees.py        2015-06-30 18:57:02 UTC (rev 14932)
+++ CalendarServer/trunk/txdav/who/test/test_group_attendees.py        2015-06-30 19:35:01 UTC (rev 14933)
</span><span class="lines">@@ -27,13 +27,14 @@
</span><span class="cx"> from twistedcaldav.config import config
</span><span class="cx"> from twistedcaldav.ical import Component, normalize_iCalStr
</span><span class="cx"> from txdav.caldav.datastore.sql_directory import GroupAttendeeRecord
</span><del>-from txdav.caldav.datastore.test.util import populateCalendarsFrom, CommonCommonTests
</del><ins>+from txdav.caldav.datastore.test.util import populateCalendarsFrom, CommonCommonTests, \
+    DateTimeSubstitutionsMixin
</ins><span class="cx"> from txdav.who.directory import CalendarDirectoryRecordMixin
</span><span class="cx"> from txdav.who.groups import GroupCacher
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class GroupAttendeeTestBase(CommonCommonTests, unittest.TestCase):
</del><ins>+class GroupAttendeeTestBase(CommonCommonTests, DateTimeSubstitutionsMixin, unittest.TestCase):
</ins><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     GroupAttendeeReconciliation tests
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="lines">@@ -50,6 +51,8 @@
</span><span class="cx">         )
</span><span class="cx">         yield self.populate()
</span><span class="cx"> 
</span><ins>+        self.setupDateTimeValues()
+
</ins><span class="cx">         self.paths = {}
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -98,7 +101,7 @@
</span><span class="cx"> 
</span><span class="cx">             return event
</span><span class="cx"> 
</span><del>-        self.assertEqual(
</del><ins>+        self.assertEqualCalendarData(
</ins><span class="cx">             orderMemberValues(Component.fromString(normalize_iCalStr(iCalStr1))),
</span><span class="cx">             orderMemberValues(Component.fromString(normalize_iCalStr(iCalStr2)))
</span><span class="cx">         )
</span><span class="lines">@@ -121,7 +124,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -137,7 +140,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 02;CUTYPE=X-SERVER-GROUP;EMAIL=group02@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group02
</span><span class="lines">@@ -154,13 +157,13 @@
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 0)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 0)
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -180,7 +183,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -196,7 +199,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CUTYPE=X-SERVER-GROUP;SCHEDULE-STATUS=3.7:urn:uuid:FFFFFFFF-EEEE-DDDD-CCCC-BBBBBBBBBBBB
</span><span class="lines">@@ -207,13 +210,13 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -230,7 +233,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -247,7 +250,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user02
</span><span class="lines">@@ -258,13 +261,13 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -287,7 +290,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -303,7 +306,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 04;CUTYPE=X-SERVER-GROUP;SCHEDULE-STATUS=2.7:urn:x-uid:group04
</span><span class="lines">@@ -319,13 +322,13 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -353,7 +356,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -371,7 +374,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -387,13 +390,13 @@
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR&quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -414,7 +417,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -430,7 +433,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -444,7 +447,7 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -459,7 +462,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -478,7 +481,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -494,7 +497,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -511,7 +514,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -530,7 +533,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -558,13 +561,13 @@
</span><span class="cx">         self.assertEqual(len(wps), 0)
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 0)
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -582,7 +585,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_3))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_3.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 1)
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -595,7 +598,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_4))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_4.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="lines">@@ -617,7 +620,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event {0}
</span><span class="cx"> UID:event{0}@ninevah.local
</span><span class="lines">@@ -633,7 +636,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event{0}@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 0{0};EMAIL=user0{0}@example.com;RSVP=TRUE:urn:x-uid:user0{0}
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -650,7 +653,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event{0}@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 0{0};EMAIL=user0{0}@example.com;RSVP=TRUE:urn:x-uid:user0{0}
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -669,7 +672,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event{0}@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 0{0};EMAIL=user0{0}@example.com;RSVP=TRUE:urn:x-uid:user0{0}
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -700,13 +703,13 @@
</span><span class="cx"> 
</span><span class="cx">         for i in userRange:
</span><span class="cx">             calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user0{0}&quot;.format(i))
</span><del>-            vcalendar = Component.fromString(data_put_1.format(i))
</del><ins>+            vcalendar = Component.fromString(data_put_1.format(i, **self.dtsubs))
</ins><span class="cx">             yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">             yield self.commit()
</span><span class="cx"> 
</span><span class="cx">             cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user0{0}&quot;.format(i))
</span><span class="cx">             vcalendar = yield cobj.component()
</span><del>-            self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2.format(i)))
</del><ins>+            self.assertEqualCalendarData(vcalendar, data_get_2.format(i, **self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 0)
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -725,7 +728,7 @@
</span><span class="cx">         for i in userRange:
</span><span class="cx">             cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user0{0}&quot;.format(i))
</span><span class="cx">             vcalendar = yield cobj.component()
</span><del>-            self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_3.format(i)))
</del><ins>+            self.assertEqualCalendarData(vcalendar, data_get_3.format(i, **self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, len(userRange))
</span><span class="cx">         yield self.commit()
</span><span class="lines">@@ -739,7 +742,7 @@
</span><span class="cx">         for i in userRange:
</span><span class="cx">             cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user0{0}&quot;.format(i))
</span><span class="cx">             vcalendar = yield cobj.component()
</span><del>-            self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_4.format(i)))
</del><ins>+            self.assertEqualCalendarData(vcalendar, data_get_4.format(i, **self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="lines">@@ -762,7 +765,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -779,7 +782,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -795,7 +798,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -813,7 +816,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -834,7 +837,7 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -848,11 +851,11 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 1)
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_2)
</del><ins>+        vcalendar = Component.fromString(data_put_2.format(**self.dtsubs))
</ins><span class="cx">         yield cobj.setComponent(vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -860,7 +863,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         wps = yield groupCacher.refreshGroup(self.transactionUnderTest(), &quot;group01&quot;)
</span><span class="cx">         self.assertEqual(len(wps), 0)
</span><span class="lines">@@ -884,7 +887,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         '''
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="lines">@@ -916,9 +919,9 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="cx"> ORGANIZER:MAILTO:user02@example.com
</span><span class="lines">@@ -934,9 +937,9 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><del>-RRULE:FREQ=DAILY;UNTIL=20140101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_back1}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="cx"> ORGANIZER:MAILTO:user02@example.com
</span><span class="lines">@@ -951,14 +954,14 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="lines">@@ -970,13 +973,13 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-RRULE:FREQ=DAILY;UNTIL=20140101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_back1}T100000
</ins><span class="cx"> SEQUENCE:1
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="lines">@@ -992,7 +995,7 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1006,11 +1009,11 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 1)
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_2)
</del><ins>+        vcalendar = Component.fromString(data_put_2.format(**self.dtsubs))
</ins><span class="cx">         yield cobj.setComponent(vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="lines">@@ -1018,7 +1021,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         wps = yield groupCacher.refreshGroup(self.transactionUnderTest(), &quot;group01&quot;)
</span><span class="cx">         if len(wps): # This is needed because the test currently fails and does actually create job items we have to wait for
</span><span class="lines">@@ -1043,7 +1046,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -1059,9 +1062,9 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="cx"> ORGANIZER:MAILTO:user02@example.com
</span><span class="lines">@@ -1076,14 +1079,14 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="lines">@@ -1095,14 +1098,14 @@
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com:urn:x-uid:group01
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> TRANSP:TRANSPARENT
</span><span class="cx"> END:VEVENT
</span><span class="lines">@@ -1120,7 +1123,7 @@
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-{relatedTo}RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+{relatedTo}RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SEQUENCE:2
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="lines">@@ -1131,7 +1134,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><del>-{uid}DTSTART:20120101T100000Z
</del><ins>+{uid}DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1156,7 +1159,7 @@
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-{relatedTo}RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+{relatedTo}RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SEQUENCE:2
</span><span class="cx"> STATUS:CANCELLED
</span><span class="cx"> SUMMARY:event 1
</span><span class="lines">@@ -1169,7 +1172,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
</span><span class="cx"> BEGIN:VEVENT
</span><del>-{uid}DTSTART:20120101T100000Z
</del><ins>+{uid}DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com:urn:x-uid:group01
</span><span class="lines">@@ -1191,21 +1194,26 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><span class="cx">         vcalendar = yield cobjs[0].componentForUser()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1_user01))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1_user01.format(**self.dtsubs))
</ins><span class="cx">         user01_cname = cobjs[0].name()
</span><span class="cx"> 
</span><ins>+        cal = yield self.calendarUnderTest(name=&quot;inbox&quot;, home=&quot;user01&quot;)
+        cobjs = yield cal.objectResources()
+        self.assertEqual(len(cobjs), 1)
+        yield cobjs[0].remove()
+
</ins><span class="cx">         self.patch(CalendarDirectoryRecordMixin, &quot;expandedMembers&quot;, expandedMembers)
</span><span class="cx"> 
</span><span class="cx">         wps = yield groupCacher.refreshGroup(self.transactionUnderTest(), &quot;group01&quot;)
</span><span class="lines">@@ -1225,22 +1233,13 @@
</span><span class="cx">                     &quot;uid&quot;: component.getProperty(&quot;UID&quot;),
</span><span class="cx">                 }
</span><span class="cx">                 break
</span><ins>+            props.update(self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">             if cobj.name() == &quot;data1.ics&quot;:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_2.format(**props)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_2.format(**props))
</ins><span class="cx">                 props_orig = props
</span><span class="cx">             else:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_3.format(**props)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_3.format(**props))
</ins><span class="cx">                 props_new = props
</span><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="lines">@@ -1248,21 +1247,17 @@
</span><span class="cx">         for cobj in cobjs:
</span><span class="cx">             vcalendar = yield cobj.componentForUser()
</span><span class="cx">             if cobj.name() == user01_cname:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_2_user01.format(**props_orig)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_2_user01.format(**props_orig))
</ins><span class="cx">             else:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_3_user01.format(**props_new)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_3_user01.format(**props_new))
</ins><span class="cx"> 
</span><ins>+        cal = yield self.calendarUnderTest(name=&quot;inbox&quot;, home=&quot;user01&quot;)
+        cobjs = yield cal.objectResources()
+        self.assertEqual(len(cobjs), 1)
+        comp = yield cobjs[0].componentForUser()
+        self.assertTrue(&quot;METHOD:CANCEL&quot; in str(comp))
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def test_groupChangeLargerSpanningEvent(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1276,9 +1271,9 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="cx"> ORGANIZER:MAILTO:user02@example.com
</span><span class="lines">@@ -1293,13 +1288,13 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20120101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="cx"> END:VCALENDAR
</span><span class="lines">@@ -1317,7 +1312,7 @@
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-{relatedTo}RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+{relatedTo}RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SEQUENCE:2
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> END:VEVENT
</span><span class="lines">@@ -1329,7 +1324,7 @@
</span><span class="cx"> CALSCALE:GREGORIAN
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><del>-{uid}DTSTART:20120101T100000Z
</del><ins>+{uid}DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1353,7 +1348,7 @@
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;MEMBER=&quot;urn:x-uid:group01&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 02;EMAIL=user02@example.com:urn:x-uid:user02
</span><del>-{relatedTo}RRULE:FREQ=DAILY;UNTIL=20240101T100000
</del><ins>+{relatedTo}RRULE:FREQ=DAILY;UNTIL={nowDate_fwd20}T100000
</ins><span class="cx"> SEQUENCE:2
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> TRANSP:TRANSPARENT
</span><span class="lines">@@ -1373,13 +1368,13 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_1))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 0)
</span><span class="cx"> 
</span><span class="lines">@@ -1402,31 +1397,19 @@
</span><span class="cx">                     &quot;uid&quot;: component.getProperty(&quot;UID&quot;),
</span><span class="cx">                 }
</span><span class="cx">                 break
</span><ins>+            props.update(self.dtsubs)
</ins><span class="cx"> 
</span><span class="cx">             if cobj.name() == &quot;data1.ics&quot;:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_2.format(**props)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_2.format(**props))
</ins><span class="cx">                 props_orig = props
</span><span class="cx">             else:
</span><del>-                self.assertEqual(
-                    normalize_iCalStr(vcalendar),
-                    normalize_iCalStr(
-                        data_get_3.format(**props)
-                    )
-                )
</del><ins>+                self.assertEqualCalendarData(vcalendar, data_get_3.format(**props))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="cx">         self.assertEqual(len(cobjs), 1)
</span><span class="cx">         vcalendar = yield cobjs[0].componentForUser()
</span><del>-        self.assertEqual(
-            normalize_iCalStr(vcalendar),
-            normalize_iCalStr(data_get_2_user01.format(**props_orig))
-        )
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2_user01.format(**props_orig))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -1452,7 +1435,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -1470,7 +1453,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1492,7 +1475,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1515,16 +1498,16 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="cx"> ATTENDEE;CN=Group 02;CUTYPE=X-SERVER-GROUP;EMAIL=group02@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group02
</span><span class="cx"> ATTENDEE;CN=Group 03;CUTYPE=X-SERVER-GROUP;EMAIL=group03@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group03
</span><del>-ATTENDEE;CN=User 06;EMAIL=user06@example.com;MEMBER=&quot;urn:x-uid:group02&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user06
</del><span class="cx"> ATTENDEE;CN=User 07;EMAIL=user07@example.com;MEMBER=&quot;urn:x-uid:group02&quot;,&quot;urn:x-uid:group03&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user07
</span><span class="cx"> ATTENDEE;CN=User 08;EMAIL=user08@example.com;MEMBER=&quot;urn:x-uid:group02&quot;,&quot;urn:x-uid:group03&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user08
</span><span class="cx"> ATTENDEE;CN=User 09;EMAIL=user09@example.com;MEMBER=&quot;urn:x-uid:group03&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user09
</span><ins>+ATTENDEE;CN=User 06;EMAIL=user06@example.com;MEMBER=&quot;urn:x-uid:group02&quot;;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;SCHEDULE-STATUS=1.2:urn:x-uid:user06
</ins><span class="cx"> CREATED:20060101T150000Z
</span><span class="cx"> ORGANIZER;CN=User 01;EMAIL=user01@example.com:urn:x-uid:user01
</span><span class="cx"> SEQUENCE:2
</span><span class="lines">@@ -1543,13 +1526,13 @@
</span><span class="cx">                 result = yield unpatchedRecordWithUID(self, uid)
</span><span class="cx">             returnValue(result)
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -1567,7 +1550,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         # remove group members run cacher again
</span><span class="cx">         self.patch(DirectoryService, &quot;recordWithUID&quot;, recordWithUID)
</span><span class="lines">@@ -1579,7 +1562,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_2)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user06&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="lines">@@ -1598,7 +1581,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_3)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_3.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         cal = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user06&quot;)
</span><span class="cx">         cobjs = yield cal.objectResources()
</span><span class="lines">@@ -1631,7 +1614,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -1648,7 +1631,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 02;CUTYPE=X-SERVER-GROUP;EMAIL=group02@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group02
</span><span class="lines">@@ -1670,7 +1653,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -1686,7 +1669,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 01;EMAIL=user01@example.com;RSVP=TRUE:urn:x-uid:user01
</span><span class="cx"> ATTENDEE;CN=Group 02;CUTYPE=X-SERVER-GROUP;EMAIL=group02@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group02
</span><span class="lines">@@ -1701,13 +1684,13 @@
</span><span class="cx"> END:VCALENDAR
</span><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -1728,15 +1711,15 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_1)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_1.format(**self.dtsubs))
</ins><span class="cx"> 
</span><del>-        vcalendar = Component.fromString(data_put_2)
</del><ins>+        vcalendar = Component.fromString(data_put_2.format(**self.dtsubs))
</ins><span class="cx">         yield cobj.setComponent(vcalendar)
</span><span class="cx">         yield self.commit()
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user01&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self._assertICalStrEqual(vcalendar, data_get_2)
</del><ins>+        self._assertICalStrEqual(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user06&quot;, 1)
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user07&quot;, 1)
</span><span class="lines">@@ -1774,7 +1757,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="cx"> UID:event1@ninevah.local
</span><span class="lines">@@ -1790,7 +1773,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20240101T100000Z
</del><ins>+DTSTART:{nowDate_fwd20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1805,7 +1788,7 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx"> 
</span><span class="cx">         groupsToRefresh = yield groupCacher.groupsToRefresh(self.transactionUnderTest())
</span><span class="lines">@@ -1822,7 +1805,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 1)
</span><span class="cx">         groupsToRefresh = yield groupCacher.groupsToRefresh(self.transactionUnderTest())
</span><span class="lines">@@ -1876,7 +1859,7 @@
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> DTSTAMP:20051222T205953Z
</span><span class="cx"> CREATED:20060101T150000Z
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> RRULE:FREQ=DAILY
</span><span class="cx"> DURATION:PT1H
</span><span class="cx"> SUMMARY:event 1
</span><span class="lines">@@ -1893,7 +1876,7 @@
</span><span class="cx"> PRODID:-//Example Inc.//Example Calendar//EN
</span><span class="cx"> BEGIN:VEVENT
</span><span class="cx"> UID:event1@ninevah.local
</span><del>-DTSTART:20140101T100000Z
</del><ins>+DTSTART:{nowDate_back20}T100000Z
</ins><span class="cx"> DURATION:PT1H
</span><span class="cx"> ATTENDEE;CN=User 02;EMAIL=user02@example.com;RSVP=TRUE:urn:x-uid:user02
</span><span class="cx"> ATTENDEE;CN=Group 01;CUTYPE=X-SERVER-GROUP;EMAIL=group01@example.com;SCHEDULE-STATUS=2.7:urn:x-uid:group01
</span><span class="lines">@@ -1909,7 +1892,7 @@
</span><span class="cx">         groupCacher = GroupCacher(self.transactionUnderTest().directoryService())
</span><span class="cx"> 
</span><span class="cx">         calendar = yield self.calendarUnderTest(name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><del>-        vcalendar = Component.fromString(data_put_1)
</del><ins>+        vcalendar = Component.fromString(data_put_1.format(**self.dtsubs))
</ins><span class="cx">         yield calendar.createCalendarObjectWithName(&quot;data1.ics&quot;, vcalendar)
</span><span class="cx"> 
</span><span class="cx">         groupsToRefresh = yield groupCacher.groupsToRefresh(self.transactionUnderTest())
</span><span class="lines">@@ -1926,7 +1909,7 @@
</span><span class="cx"> 
</span><span class="cx">         cobj = yield self.calendarObjectUnderTest(name=&quot;data1.ics&quot;, calendar_name=&quot;calendar&quot;, home=&quot;user02&quot;)
</span><span class="cx">         vcalendar = yield cobj.component()
</span><del>-        self.assertEqual(normalize_iCalStr(vcalendar), normalize_iCalStr(data_get_2))
</del><ins>+        self.assertEqualCalendarData(vcalendar, data_get_2.format(**self.dtsubs))
</ins><span class="cx"> 
</span><span class="cx">         yield self._verifyObjectResourceCount(&quot;user01&quot;, 1)
</span><span class="cx">         groupsToRefresh = yield groupCacher.groupsToRefresh(self.transactionUnderTest())
</span></span></pre>
</div>
</div>

</body>
</html>