[CalendarServer-changes] [7090] CalendarServer/branches/users/cdaboo/pycalendar

source_changes at macosforge.org source_changes at macosforge.org
Tue Mar 1 12:28:31 PST 2011


Revision: 7090
          http://trac.macosforge.org/projects/calendarserver/changeset/7090
Author:   cdaboo at apple.com
Date:     2011-03-01 12:28:29 -0800 (Tue, 01 Mar 2011)
Log Message:
-----------
Work in progress snapshot. ical.py now mostly implemented using pycalendar with test_icalendar.py passing.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py
    CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -24,7 +24,6 @@
     "dateordatetime",
     "timerange",
     "asTimeZone",
-    "asUTC",
     "iCalendarString",
 ]
 
@@ -32,7 +31,7 @@
 datetime = __import__("datetime").datetime
 
 from vobject.icalendar import dateTimeToString, dateToString
-from vobject.icalendar import utc, getTzid as tzWithID
+from vobject.icalendar import utc
 
 
 # FIXME, add constants for begining/end of time
@@ -297,21 +296,17 @@
 # Convenience functions
 ##
 
-def asTimeZone(dateOrDatetime, tzinfo):
+def asTimeZone(pydt, pytz):
     """
-    Convert a L{date} or L{datetime} to the given time zone.
+    Convert a L{PyCalendarDateTime} to the given time zone.
     """
-    return dateordatetime(dateOrDatetime).asTimeZone(tzinfo).dateOrDatetime()
+    dup = pydt.duplicate()
+    dup.adjustTimezone(pytz)
+    return dup
 
-def asUTC(dateOrDatetime):
+def iCalendarString(pydt):
     """
-    Convert a L{date} or L{datetime} to UTC.
-    """
-    return dateordatetime(dateOrDatetime).asUTC().dateOrDatetime()
-
-def iCalendarString(dateOrDatetime):
-    """
-    Convert a L{date} or L{datetime} to a string appropriate for use
+    Convert a L{PyCalendarDateTime} to a string appropriate for use
     in an iCalendar property.
     """
-    return dateordatetime(dateOrDatetime).iCalendarString()
+    return pydt.getText()

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from pycalendar.datetime import PyCalendarDateTime
 
 """
 CalDAV XML Support.
@@ -34,7 +35,6 @@
 from twext.python.log import Logger
 
 from twistedcaldav.ical import Component as iComponent
-from twistedcaldav.ical import parse_date_or_datetime
 
 log = Logger()
 
@@ -93,8 +93,8 @@
         if "start" not in attributes and "end" not in attributes:
             raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
         
-        self.start = parse_date_or_datetime(attributes["start"]) if "start" in attributes else None
-        self.end = parse_date_or_datetime(attributes["end"]) if "end" in attributes else None
+        self.start = PyCalendarDateTime.parseText(attributes["start"]) if "start" in attributes else None
+        self.end = PyCalendarDateTime.parseText(attributes["end"]) if "end" in attributes else None
 
     def valid(self, level=0):
         """

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.period import PyCalendarPeriod
+import datetime
+from vobject.icalendar import utc
 
 """
 Date/time Utilities
@@ -30,91 +35,98 @@
 ]
 
 import calendar
-import datetime
-from vobject.icalendar import utc
 
-from twext.python.datetime import dateordatetime
-
 def normalizeForIndex(dt):
     """
-    Normalize a L{datetime.date} or L{datetime.datetime} object for use in the Index.
-    If it's a L{datetime.date}, convert to L{datetime.datetime} with HH:MM:SS set to 00:00:00 in UTC.
-    If it's a L{datetime.datetime}, convert to UTC.
-    @param dt: a L{datetime.date} or L{datetime.datetime} object to normalize
-    @return: the normalized date or datetime
+    Normalize a L{PyCalendarDateTime} object for use in the Index.
+    Convert to date-time in UTC.
+    @param dt: a L{PyCalendarDateTime} object to normalize
+    @return: the normalized PyCalendarDateTime
     """
-    if not isinstance(dt, datetime.date):
-        raise TypeError("%r is not a datetime.date instance" % (dt,))
+    if not isinstance(dt, PyCalendarDateTime):
+        raise TypeError("%r is not a removeParameterValue instance" % (dt,))
     
-    if isinstance(dt, datetime.datetime):
-        if dt.tzinfo is not None:
-            return dt.astimezone(utc)
-        else:
-            return dt
+    dt = dt.duplicate()
+    if dt.isDateOnly():
+        dt.setDateOnly(False)
+        dt.setHHMMSS(0, 0, 0)
+        dt.setTimezoneUTC(True)
+        return dt
+    elif dt.floating():
+        return dt
     else:
-        return datetime.datetime.fromordinal(dt.toordinal())
+        dt.adjustToUTC()
+        return dt
 
 def normalizeToUTC(dt):
     """
-    Normalize a L{datetime.date} or L{datetime.datetime} object to UTC.
+    Normalize a L{PyCalendarDateTime} object to UTC.
     """
-    if not isinstance(dt, datetime.date):
-        raise TypeError("%r is not a datetime.date instance" % (dt,))
+    if not isinstance(dt, PyCalendarDateTime):
+        raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
     
-    if isinstance(dt, datetime.datetime):
-        if dt.tzinfo is not None:
-            return dt.astimezone(utc)
-        else:
-            return dt.replace(tzinfo=utc)
+    dt = dt.duplicate()
+    if dt.isDateOnly():
+        dt.setDateOnly(False)
+        dt.setHHMMSS(0, 0, 0)
+        dt.setTimezoneUTC(True)
+        return dt
+    elif dt.floating():
+        dt.setTimezoneUTC(True)
+        return dt
     else:
-        return datetime.datetime.fromordinal(dt.toordinal()).replace(tzinfo=utc)
+        dt.adjustToUTC()
+        return dt
 
-def floatoffset(dt, tzinfo):
+def floatoffset(dt, pytz):
     """
     Apply the timezone offset to the supplied time, then force tz to utc. This gives the local
     date-time as if the local tz were UTC. It can be used in floating time comparisons with UTC date-times.
     
-    @param dt: a L{datetime.datetime} object to normalize
-    @param tzinfo: a L{datetime.tzinfo} object to apply offset from
-    @return: the normalized datetime
+    @param dt: a L{PyCalendarDateTime} object to normalize
+    @param pytz: a L{PyCalendarTimezone} object to apply offset from
+    @return: the normalized PyCalendarDateTime
     """
     
-    if tzinfo is None:
-        tzinfo = utc
-    return dt.astimezone(tzinfo).replace(tzinfo=utc)
+    if pytz is None:
+        pytz = PyCalendarTimezone(utc=True)
+    
+    dt = dt.duplicate()
+    dt.adjustTimezone(pytz)
+    dt.setTimezoneUTC(True)
+    return dt
 
+def adjustFloatingToTimezone(dtadjust, dtcopyfrom, pytz=None):
+    
+    dtadjust = dtadjust.duplicate()
+    dtadjust.setTimezone(pytz if pytz else dtcopyfrom.getTimezone())
+    return dtadjust
+
 def compareDateTime(dt1, dt2, defaulttz=None):
-    dt1 = dateordatetime(dt1, defaultTZ=defaulttz)
-    dt2 = dateordatetime(dt2, defaultTZ=defaulttz)
-    if dt1 == dt2:
-        return 0
-    elif dt1 < dt2:
-        return -1
-    else:
-        return 1
+    
+    if dt1.floating() and not dt2.floating():
+        dt1 = adjustFloatingToTimezone(dt1, dt2, defaulttz)
+    elif dt2.floating() and not dt1.floating():
+        dt2 = adjustFloatingToTimezone(dt2, dt1, defaulttz)
+    
+    return dt1.compareDateTime(dt2)
 
 def differenceDateTime(start, end, defaulttz = None):
-    return dateordatetime(end, defaultTZ=defaulttz) - dateordatetime(start)
 
-#def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
-#    def dodt(d):
-#        if d is None:
-#            return None
-#        else:
-#            return dateordatetime(d, defaulttz)
-#
-#    dodt1 = timerange(dodt(start1), dodt(end1))
-#    dodt2 = timerange(dodt(start2), dodt(end2))
-#
-#    return dodt1.overlapsWith(dodt2)
+    if start.floating() and not end.floating():
+        start = adjustFloatingToTimezone(start, end, defaulttz)
+    elif end.floating() and not start.floating():
+        end = adjustFloatingToTimezone(end, start, defaulttz)
 
+    return end - start
+
 def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
-    # Can't compare datetime.date and datetime.datetime objects, so normalize
-    # to date if they are mixed.
-    if isinstance(start1, datetime.datetime) and (start2 is not None) and not isinstance(start2, datetime.datetime): start1 = start1.date()
-    if isinstance(start2, datetime.datetime) and (start1 is not None) and not isinstance(start1, datetime.datetime): start2 = start2.date()
-    if isinstance(end1,   datetime.datetime) and (end2 is not None) and not isinstance(end2,   datetime.datetime): end1   = end1.date()
-    if isinstance(end2,   datetime.datetime) and (end1 is not None) and not isinstance(end1,   datetime.datetime): end2   = end2.date()
+    # Can't compare date-time and date only, so normalize
+    # to date only if they are mixed.
+    if not start1.isDateOnly() and (start2 is not None) and start2.isDateOnly(): start1 = start1.setDateOnly(True)
+    if not start2.isDateOnly() and (start1 is not None) and start1.isDateOnly(): start2 = start2.setDateOnly(True)
+    if not end1.isDateOnly() and (end2 is not None) and end2.isDateOnly(): end1 = end1.setDateOnly(True)
+    if not end2.isDateOnly() and (end1 is not None) and end1.isDateOnly(): end2 = end2.setDateOnly(True)
 
     # Note that start times are inclusive and end times are not.
     if start1 is not None and start2 is not None:
@@ -133,26 +145,8 @@
     else:
         return False
 
-def periodEnd(p):
+def normalizePeriodList(periods):
     """
-    Calculate the end datetime of the period. Since a period is a
-    tuple consisting of a pair of L{datetime.datetime}'s, or one
-    L{datetime.datetime} and one L{datetime.timedelta}, we may need
-    to add the duration to the start to get the actual end.
-    @param p: the period whose end is to be determined.
-    @return: the L{datetime.datetime} for the end.
-    """
-    assert len(p) == 2, "Period is not a tuple of two items: %r" % (p,)
-    assert isinstance(p[0], datetime.datetime), "Period start is not a datetime: %r" % (p,)
-    assert isinstance(p[1], datetime.datetime) or isinstance(p[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p,)
-    
-    if isinstance(p[1], datetime.timedelta):
-        return p[0] + p[1]
-    else:
-        return p[1]
-    
-def normalizePeriodList(list):
-    """
     Normalize the list of periods by merging overlapping or consecutive ranges
     and sorting the list by each periods start.
     @param list: a list of tuples of L{datetime.datetime} pairs. The list is changed in place.
@@ -169,47 +163,42 @@
         @return: 1 if p1>p2, 0 if p1==p2, -1 if p1<p2
         """
 
-        assert len(p1) == 2, "Period is not a tuple of two items: %r" % (p1,)
-        assert isinstance(p1[0], datetime.datetime), "Period start is not a datetime: %r" % (p1,)
-        assert isinstance(p1[1], datetime.datetime) or isinstance(p1[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p1,)
+        assert isinstance(p1, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p1,)
+        assert isinstance(p2, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p2,)
         
-        assert len(p2) == 2, "Period is not a tuple of two items: %r" % (p2,)
-        assert isinstance(p2[0], datetime.datetime), "Period start is not a datetime: %r" % (p2,)
-        assert isinstance(p2[1], datetime.datetime) or isinstance(p2[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p2,)
         
-        
-        if p1[0] == p2[0]:
-            cmp1 = periodEnd(p1)
-            cmp2 = periodEnd(p2)
+        if p1.getStart() == p2.getStart():
+            cmp1 = p1.getEnd()
+            cmp2 = p2.getEnd()
         else:
-            cmp1 = p1[0]
-            cmp2 = p2[0]
+            cmp1 = p1.getStart()
+            cmp2 = p2.getStart()
         
         return compareDateTime(cmp1, cmp2)
 
-    list.sort(cmp=sortPeriods)
+    periods.sort(cmp=sortPeriods)
     
     # Now merge overlaps and consecutive periods
     index = None
     p = None
     pe = None
-    for i in xrange(len(list)):
+    for i in xrange(len(periods)):
         if p is None:
             index = i
-            p = list[i]
-            pe = periodEnd(p)
+            p = periods[i]
+            pe = p.getEnd()
             continue
-        ie = periodEnd(list[i])
-        if (pe >= list[i][0]):
+        ie = periods[i].getEnd()
+        if (pe >= periods[i].getStart()):
             if ie > pe:
-                list[index] = (list[index][0], ie)
+                periods[index] = (periods[index].getStart(), ie)
                 pe = ie
-            list[i] = None
+            periods[i] = None
         else:
             index = i
-            p = list[i]
-            pe = periodEnd(p)
-    list[:] = [x for x in list if x]
+            p = periods[i]
+            pe =p.getEnd()
+    periods[:] = [x for x in periods if x]
 
 def clipPeriod(period, clipPeriod):
     """
@@ -219,10 +208,10 @@
     @return: the (start, end) tuple for the clipped period, or
              None if the period is outside the clip period
     """
-    start = period[0]
-    end = periodEnd(period)
-    clipStart = clipPeriod[0]
-    clipEnd = periodEnd(clipPeriod)
+    start = period.getStart()
+    end = period.getEnd()
+    clipStart = clipPeriod.getStart()
+    clipEnd = clipPeriod.getEnd()
 
     if start < clipStart:
         start = clipStart
@@ -234,10 +223,9 @@
         return None
     else:
         # Try to preserve use of duration in period
-        if isinstance(period[1], datetime.timedelta):
-            return (start, end - start)
-        else:
-            return (start, end)
+        result = PyCalendarPeriod(start, end)
+        result.setUseDuration(period.getUseDuration())
+        return result
 
 def parseSQLTimestamp(ts):
     

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -14,6 +14,16 @@
 # limitations under the License.
 ##
 
+from pycalendar import definitions
+from pycalendar.attribute import PyCalendarAttribute
+from pycalendar.calendar import PyCalendar
+from pycalendar.componentbase import PyCalendarComponentBase
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.period import PyCalendarPeriod
+from pycalendar.property import PyCalendarProperty
+from pycalendar.timezone import PyCalendarTimezone
+
 """
 iCalendar Utilities
 """
@@ -24,26 +34,14 @@
     "allowedComponents",
     "Property",
     "Component",
-    "FixedOffset",
-    "parse_date",
-    "parse_time",
-    "parse_datetime",
-    "parse_date_or_datetime",
-    "parse_duration",
     "tzexpand",
 ]
 
 import cStringIO as StringIO
-import datetime
 import heapq
 import itertools
 
-from vobject import newFromBehavior, readComponents
-from vobject.base import Component as vComponent, ContentLine as vContentLine, ParseError as vParseError
-from vobject.icalendar import TimezoneComponent, dateTimeToString, deltaToOffset, getTransition, stringToDate, stringToDateTime, stringToDurations, utc
-
 from twext.python.log import Logger
-from twext.python.datetime import dateordatetime, timerange, asUTC, iCalendarString
 from twext.web2.stream import IStream
 from twext.web2.dav.util import allDataFromStream
 
@@ -81,7 +79,7 @@
     "GEO":          (None, {"VALUE": "FLOAT"}),
     "LOCATION":     (None, {"VALUE": "TEXT"}),
     "PERCENT-COMPLETE": (None, {"VALUE": "INTEGER"}),
-    "PRIORITY":     ("0", {"VALUE": "INTEGER"}),
+    "PRIORITY":     (0, {"VALUE": "INTEGER"}),
     "RESOURCES":    (None, {"VALUE": "TEXT"}),
     "STATUS":       (None, {"VALUE": "TEXT"}),
     "SUMMARY":      (None, {"VALUE": "TEXT"}),
@@ -116,12 +114,12 @@
     "RDATE":        (None, {"VALUE": "DATE-TIME"}),
     "RRULE":        (None, {"VALUE": "RECUR"}),
     "ACTION":       (None, {"VALUE": "TEXT"}),
-    "REPEAT":       ("0", {"VALUE": "INTEGER"}),
+    "REPEAT":       (0, {"VALUE": "INTEGER"}),
     "TRIGGER":      (None, {"VALUE": "DURATION"}),
     "CREATED":      (None, {"VALUE": "DATE-TIME"}),
     "DTSTAMP":      (None, {"VALUE": "DATE-TIME"}),
     "LAST-MODIFIED": (None, {"VALUE": "DATE-TIME"}),
-    "SEQUENCE":     ("0", {"VALUE": "INTEGER"}),
+    "SEQUENCE":     (0, {"VALUE": "INTEGER"}),
     "REQUEST-STATUS": (None, {"VALUE": "TEXT"}),
 }
 
@@ -151,18 +149,19 @@
             assert value  is None
             assert params is None
 
-            vobj = kwargs["vobject"]
+            pyobj = kwargs["pycalendar"]
 
-            if not isinstance(vobj, vContentLine):
-                raise TypeError("Not a vContentLine: %r" % (property,))
+            if not isinstance(pyobj, PyCalendarProperty):
+                raise TypeError("Not a PyCalendarProperty: %r" % (property,))
 
-            self._vobject = vobj
+            self._pycalendar = pyobj
         else:
-            # Convert params dictionary to list of lists format used by vobject
-            lparams = [[key] + lvalue for key, lvalue in params.items()]
-            self._vobject = vContentLine(name, lparams, value, isNative=True)
+            # Convert params dictionary to list of lists format used by pycalendar
+            self._pycalendar = PyCalendarProperty(name, value)
+            for attrname, attrvalue in params.items():
+                self._pycalendar.addAttribute(PyCalendarAttribute(attrname, attrvalue))
 
-    def __str__ (self): return self._vobject.serialize()
+    def __str__ (self): return str(self._pycalendar)
     def __repr__(self): return "<%s: %r: %r>" % (self.__class__.__name__, self.name(), self.value())
 
     def __hash__(self):
@@ -171,7 +170,7 @@
     def __ne__(self, other): return not self.__eq__(other)
     def __eq__(self, other):
         if not isinstance(other, Property): return False
-        return self.name() == other.name() and self.value() == other.value() and self.params() == other.params()
+        return self._pycalendar == other._pycalendar
 
     def __gt__(self, other): return not (self.__eq__(other) or self.__lt__(other))
     def __lt__(self, other):
@@ -186,11 +185,11 @@
     def __ge__(self, other): return self.__eq__(other) or self.__gt__(other)
     def __le__(self, other): return self.__eq__(other) or self.__lt__(other)
 
-    def name  (self): return self._vobject.name
+    def name  (self): return self._pycalendar.getName()
 
-    def value (self): return self._vobject.value
+    def value (self): return self._pycalendar.getValue().getValue()
     def setValue(self, value):
-        self._vobject.value = value
+        self._pycalendar.setValue(value)
 
     def params(self):
         """
@@ -199,20 +198,38 @@
         Keys are parameter names, values are sequences containing
         values for the named parameter.
         """
-        return self._vobject.params
+        result = {}
+        for pyattrlist in self._pycalendar.getAttributes().values():
+            for pyattr in pyattrlist:
+                result.setdefault(pyattr.getName(), []).extend(pyattr.getValues())
+        return result
 
     def paramValue(self, name):
         """
         Returns a single value for the given parameter.  Raises
         InvalidICalendarDataError if the parameter has more than one value.
         """
-        values = self._vobject.params.get(name, [None,])
-        assert type(values) is list, "vobject returned non-list value for parameter %r in property %r" % (name, self)
-        if len(values) != 1:
-            raise InvalidICalendarDataError("Not exactly one %s value in property %r" % (name, self))
-        return values[0]
+        try:
+            return self._pycalendar.getAttributeValue(name)
+        except KeyError:
+            return None
 
-    def containsTimeRange(self, start, end, tzinfo=None):
+    def setParameter(self, paramname, paramvalue):
+        self._pycalendar.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
+
+    def removeParameter(self, paramname):
+        self._pycalendar.removeAttributes(paramname)
+
+    def removeParameterValue(self, paramname, paramvalue):
+        
+        for attr in tuple(self._pycalendar.getAttributes()):
+            if attr.getName() == paramname:
+                for value in attr.getValues():
+                    if value == paramvalue:
+                        if not attr.removeValue(value):
+                            self._pycalendar.removeAttributes(paramname)
+
+    def containsTimeRange(self, start, end, defaulttz=None):
         """
         Determines whether this property contains a date/date-time within the specified
         start/end period.
@@ -223,7 +240,7 @@
         @param end: a L{datetime.datetime} or L{datetime.date} specifying the
             end of the given time span.  C{end} may be None, indicating that
             there is no end date.
-        @param tzinfo: the default L{datetime.tzinfo} to use in datetime comparisons.
+        @param defaulttz: the default L{PyTimezone} to use in datetime comparisons.
         @return: True if the property's date/date-time value is within the given time range,
                  False if not, or the property is not an appropriate date/date-time value.
         """
@@ -234,24 +251,11 @@
             return False
         
         # get date/date-time value
-        dt = self.value()
-        assert isinstance(dt, datetime.date), "Not a date/date-time value: %r" % (self,)
+        dt = self.getDateTimeValue().getValue()
+        assert isinstance(dt, PyCalendarDateTime), "Not a date/date-time value: %r" % (self,)
         
-        return timeRangesOverlap(dt, None, start, end, tzinfo)
+        return timeRangesOverlap(dt, None, start, end, defaulttz)
 
-    def transformAllFromNative(self):
-        transformed = self._vobject.isNative
-        if transformed:
-            self._vobject = self._vobject.transformFromNative()
-            self._vobject.transformChildrenFromNative()
-        return transformed
-        
-    def transformAllToNative(self):
-        transformed = not self._vobject.isNative
-        if transformed:
-            self._vobject = self._vobject.transformToNative()
-            self._vobject.transformChildrenToNative()
-        return transformed
 
 class Component (object):
     """
@@ -302,15 +306,12 @@
         @return: a L{Component} representing the first component described by
             C{stream}.
         """
-        try:
-            return clazz(None, vobject=readComponents(stream, findBegin=False).next())
-        except UnicodeDecodeError, e:
+        cal = PyCalendar()
+        result = cal.parse(stream)
+        if not result:
             stream.seek(0)
-            raise InvalidICalendarDataError("%s: %s" % (e, stream.read()))
-        except vParseError, e:
-            raise InvalidICalendarDataError(e)
-        except StopIteration, e:
-            raise InvalidICalendarDataError(e)
+            raise InvalidICalendarDataError("%s" % (stream.read(),))
+        return clazz(None, pycalendar=cal)
 
     @classmethod
     def fromIStream(clazz, stream):
@@ -338,14 +339,14 @@
             component.
         """
         if name is None:
-            if "vobject" in kwargs:
-                vobj = kwargs["vobject"]
+            if "pycalendar" in kwargs:
+                pyobj = kwargs["pycalendar"]
 
-                if vobj is not None:
-                    if not isinstance(vobj, vComponent):
-                        raise TypeError("Not a vComponent: %r" % (vobj,))
+                if pyobj is not None:
+                    if not isinstance(pyobj, PyCalendarComponentBase):
+                        raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
 
-                self._vobject = vobj
+                self._pycalendar = pyobj
             else:
                 raise AssertionError("name may not be None")
 
@@ -362,59 +363,38 @@
             else:
                 self._parent = None
         else:
-            self._vobject = newFromBehavior(name)
+            # FIXME: figure out creating an arbitrary component
+            raise NotImplementedError
+            self._pycalendar = PyCalendar.makeComponent(name)
             self._parent = None
 
-    def __str__ (self): return self._vobject.serialize()
-    def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, str(self._vobject))
+    def __str__ (self):
+        return str(self._pycalendar)
 
+    def __repr__(self):
+        return "<%s: %r>" % (self.__class__.__name__, str(self._pycalendar))
+
     def __hash__(self):
         return hash(str(self))
 
-    def __ne__(self, other): return not self.__eq__(other)
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
     def __eq__(self, other):
         if not isinstance(other, Component):
             return False
+        return self._pycalendar == other._pycalendar
 
-        my_properties = set(self.properties())
-        for property in other.properties():
-            if property in my_properties:
-                my_properties.remove(property)
-            else:
-                return False
-        if my_properties:
-            return False
-
-        my_subcomponents = set(self.subcomponents())
-        for subcomponent in other.subcomponents():
-            for testcomponent in my_subcomponents:
-                if subcomponent == testcomponent:
-                    my_subcomponents.remove(testcomponent)
-                    break
-            else:
-                return False
-        if my_subcomponents:
-            return False
-
-        return True
-
     # FIXME: Should this not be in __eq__?
     def same(self, other):
-        return self._vobject == other._vobject
+        return self._pycalendar == other._pycalendar
     
     def name(self):
         """
         @return: the name of the iCalendar type of this component.
         """
-        return self._vobject.name
+        return self._pycalendar.getType()
 
-    def setBehavior(self, behavior):
-        """
-        Set the behavior of the underlying iCal object.
-        @param behavior: the behavior type to set.
-        """
-        self._vobject.setBehavior(behavior)
-
     def mainType(self):
         """
         Determine the primary type of iCal component in this calendar.
@@ -483,13 +463,13 @@
         assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (self,)
         
         if isinstance(recurrence_id, str):
-            recurrence_id = parse_date_or_datetime(recurrence_id) if recurrence_id else None
+            recurrence_id = PyCalendarDateTime.parseText(recurrence_id) if recurrence_id else None
 
         for component in self.subcomponents():
             if component.name() in ignoredComponents:
                 continue
             rid = component.getRecurrenceIDUTC()
-            if rid and recurrence_id and dateordatetime(rid) == recurrence_id:
+            if rid and recurrence_id and rid == recurrence_id:
                 return component
             elif rid is None and recurrence_id is None:
                 return component
@@ -513,7 +493,7 @@
         Duplicate this object and all its contents.
         @return: the duplicated calendar.
         """
-        return Component(None, vobject=vComponent.duplicate(self._vobject))
+        return Component(None, pycalendar=self._pycalendar.duplicate())
         
     def subcomponents(self):
         """
@@ -521,9 +501,8 @@
             of this component.
         """
         return (
-            Component(None, vobject=c, parent=self)
-            for c in self._vobject.getChildren()
-            if isinstance(c, vComponent)
+            Component(None, pycalendar=c, parent=self)
+            for c in self._pycalendar.getAllComponents()
         )
 
     def addComponent(self, component):
@@ -532,7 +511,7 @@
         @param component: the L{Component} to add as a subcomponent of this
             component.
         """
-        self._vobject.add(component._vobject)
+        self._pycalendar.addComponent(component._pycalendar)
         component._parent = self
 
     def removeComponent(self, component):
@@ -540,17 +519,14 @@
         Removes a subcomponent from this component.
         @param component: the L{Component} to remove.
         """
-        self._vobject.remove(component._vobject)
+        self._pycalendar.removeComponent(component._pycalendar)
 
     def hasProperty(self, name):
         """
         @param name: the name of the property whose existence is being tested.
         @return: True if the named property exists, False otherwise.
         """
-        try:
-            return len(self._vobject.contents[name.lower()]) > 0
-        except KeyError:
-            return False
+        return self._pycalendar.hasProperty(name)
 
     def getProperty(self, name):
         """
@@ -571,18 +547,15 @@
         @return: an iterable of L{Property} objects, one for each property of
             this component.
         """
+        properties = []
         if name is None:
-            properties = self._vobject.getChildren()
-        else:
-            try:
-                properties = self._vobject.contents[name.lower()]
-            except KeyError:
-                return ()
+            [properties.extend(i) for i in self._pycalendar.getProperties().values()]
+        elif self._pycalendar.countProperty(name) > 0:
+            properties = self._pycalendar.getProperties()[name]
 
         return (
-            Property(None, None, None, vobject=p)
+            Property(None, None, None, pycalendar=p)
             for p in properties
-            if isinstance(p, vContentLine)
         )
 
     def propertyValue(self, name):
@@ -594,30 +567,6 @@
         return None
 
 
-    def propertyNativeValue(self, name):
-        """
-        Return the native property value for the named property in the supplied component.
-        NB Assumes a single property exists in the component.
-        @param name: the name of the property whose value is required
-        @return: the native property value
-        """
-        properties = tuple(self.properties(name))
-
-        if len(properties) == 1:
-            transormed = properties[0].transformAllToNative()
-    
-            result = properties[0].value()
-    
-            if transormed:
-                properties[0].transformAllFromNative()
-                
-            return result
-
-        elif len(properties) > 1:
-            raise InvalidICalendarDataError("More than one %s property in component %r" % (name, self))
-        else:
-            return None
-
     def getStartDateUTC(self):
         """
         Return the start date or date-time for the specified component
@@ -625,11 +574,8 @@
         @param component: the Component whose start should be returned.
         @return: the datetime.date or datetime.datetime for the start.
         """
-        dtstart = self.propertyNativeValue("DTSTART")
-        if dtstart is not None:
-            return asUTC(dtstart)
-        else:
-            return None
+        dtstart = self.propertyValue("DTSTART")
+        return dtstart.duplicateAsUTC() if dtstart is not None else None
  
     def getEndDateUTC(self):
         """
@@ -639,17 +585,14 @@
         @param component: the Component whose end should be returned.
         @return: the datetime.date or datetime.datetime for the end.
         """
-        dtend = self.propertyNativeValue("DTEND")
+        dtend = self.propertyValue("DTEND")
         if dtend is None:
-            dtstart = self.propertyNativeValue("DTSTART")
-            duration = self.propertyNativeValue("DURATION")
+            dtstart = self.propertyValue("DTSTART")
+            duration = self.propertyValue("DURATION")
             if duration is not None:
                 dtend = dtstart + duration
 
-        if dtend is not None:
-            return asUTC(dtend)
-        else:
-            return None
+        return dtend.duplicateAsUTC() if dtend is not None else None
 
     def getDueDateUTC(self):
         """
@@ -658,17 +601,14 @@
         @param component: the Component whose start should be returned.
         @return: the datetime.date or datetime.datetime for the start.
         """
-        due = self.propertyNativeValue("DUE")
+        due = self.propertyValue("DUE")
         if due is None:
-            dtstart = self.propertyNativeValue("DTSTART")
-            duration = self.propertyNativeValue("DURATION")
+            dtstart = self.propertyValue("DTSTART")
+            duration = self.propertyValue("DURATION")
             if dtstart is not None and duration is not None:
                 due = dtstart + duration
 
-        if due is not None:
-            return asUTC(due)
-        else:
-            return None
+        return due.duplicateAsUTC() if due is not None else None
  
     def getRecurrenceIDUTC(self):
         """
@@ -676,12 +616,8 @@
         @param component: the Component whose r-id should be returned.
         @return: the datetime.date or datetime.datetime for the r-id.
         """
-        rid = self.propertyNativeValue("RECURRENCE-ID")
-
-        if rid is not None:
-            return asUTC(rid)
-        else:
-            return None
+        rid = self.propertyValue("RECURRENCE-ID")
+        return rid.duplicateAsUTC() if rid is not None else None
  
     def getRange(self):
         """
@@ -710,7 +646,7 @@
         assert self.name() == "VALARM", "Component is not a VAlARM: %r" % (self,)
         
         # The trigger value
-        trigger = self.propertyNativeValue("TRIGGER")
+        trigger = self.propertyValue("TRIGGER")
         if trigger is None:
             raise InvalidICalendarDataError("VALARM has no TRIGGER property: %r" % (self,))
         
@@ -722,26 +658,21 @@
             related = (related == "START")
         
         # Repeat property
-        repeat = self.propertyNativeValue("REPEAT")
+        repeat = self.propertyValue("REPEAT")
         if repeat is None: repeat = 0
         else: repeat = int(repeat)
         
         # Duration property
-        duration = self.propertyNativeValue("DURATION")
+        duration = self.propertyValue("DURATION")
 
         if repeat > 0 and duration is None:
             raise InvalidICalendarDataError("VALARM has invalid REPEAT/DURATIOn properties: %r" % (self,))
 
         return (trigger, related, repeat, duration)
  
-    def getRRuleSet(self, addRDate = False):
-        self.transformAllToNative()
-        return self._vobject.getrruleset(addRDate)
+    def getRecurrenceSet(self):
+        return self._pycalendar.getRecurrenceSet()
 
-    def setRRuleSet(self, rruleset):
-        #self.transformAllToNative()
-        return self._vobject.setrruleset(rruleset)
-
     def getEffectiveStartEnd(self):
         # Get the start/end range needed for instance comparisons
 
@@ -777,14 +708,14 @@
         Adds a property to this component.
         @param property: the L{Property} to add to this component.
         """
-        self._vobject.add(property._vobject)
+        self._pycalendar.addProperty(property._pycalendar)
 
     def removeProperty(self, property):
         """
         Remove a property from this component.
         @param property: the L{Property} to remove from this component.
         """
-        self._vobject.remove(property._vobject)
+        self._pycalendar.removeProperty(property._pycalendar)
 
     def replaceProperty(self, property):
         """
@@ -793,8 +724,7 @@
         """
         
         # Remove all existing ones first
-        for removeit in tuple(self.properties(property.name())):
-            self.removeProperty(removeit)
+        self._pycalendar.removeProperties(property.name())
         self.addProperty(property)
 
     def timezoneIDs(self):
@@ -806,20 +736,10 @@
         result = set()
 
         for property in self.properties():
-            for propertyname in ("TZID", "X-VOBJ-ORIGINAL-TZID"):
-                tzid = property.paramValue(propertyname)
-                if tzid is not None:
-                    result.add(tzid)
-                    break
-            else:
-                items = property.value()
-                if type(items) is not list:
-                    items = [items]
-                for item in items:
-                    tzinfo = getattr(item, 'tzinfo', None)
-                    tzid = TimezoneComponent.pickTzid(tzinfo)
-                    if tzid is not None:
-                        result.add(tzid)
+            tzid = property.paramValue("TZID")
+            if tzid is not None:
+                result.add(tzid)
+                break
         
         return result
     
@@ -848,47 +768,48 @@
         @type maximumCount: C{int}
         @return: a C{bool} indicating whether a change was made or not
         """
-
+        
         changed = False
         master = self.masterComponent()
         if master and master.isRecurring():
-            rrules = master.getRRuleSet()
+            rrules = master._pycalendar.getRecurrenceSet()
             if rrules:
-                for rrule in rrules._rrule:
-                    if rrule._count is not None:
+                for rrule in rrules.getRules():
+                    if rrule.getUseCount():
                         # Make sure COUNT is less than the limit
-                        if rrule._count > maximumCount:
-                            rrule._count = maximumCount
+                        if rrule.getCount() > maximumCount:
+                            rrule.setCount(maximumCount)
                             changed = True
-                    elif rrule._until is not None:
+                    elif rrule.getUseUntil():
                         # Need to figure out how to determine number of instances
                         # with this UNTIL and truncate if needed
                         start = master.getStartDateUTC()
-                        diff = differenceDateTime(start, rrule._until)
-                        diff = diff.days * 24 * 60 * 60 + diff.seconds
+                        diff = differenceDateTime(start, rrule.getUntil())
+                        diff = diff.getDays() * 24 * 60 * 60 + diff.getSeconds()
                         
                         period = {
-                            0: 365 * 24 * 60 * 60,
-                            1:  30 * 24 * 60 * 60,
-                            2:   7 * 24 * 60 * 60,
-                            3:   1 * 24 * 60 * 60,
-                            4:   60 * 60,
-                            5:   60,
-                            6:   1
-                        }[rrule._freq] * rrule._interval
+                            definitions.eRecurrence_YEARLY:   365 * 24 * 60 * 60,
+                            definitions.eRecurrence_MONTHLY:  30 * 24 * 60 * 60,
+                            definitions.eRecurrence_WEEKLY:   7 * 24 * 60 * 60,
+                            definitions.eRecurrence_DAILY:    1 * 24 * 60 * 60,
+                            definitions.eRecurrence_HOURLY:   60 * 60,
+                            definitions.eRecurrence_MINUTELY: 60,
+                            definitions.eRecurrence_SECONDLY: 1
+                        }[rrule.getFreq()] * rrule.getInterval()
                         
                         if diff / period > maximumCount:
-                            rrule._until = None
-                            rrule._count = maximumCount
+                            rrule.setUseUntil(False)
+                            rrule.setUseCount(True)
+                            rrule.setCount(maximumCount)
+                            rrules.changed()
                             changed = True
                     else:
                         # For frequencies other than yearly we will truncate at our limit
-                        if rrule._freq != 0:
-                            rrule._count = maximumCount
+                        if rrule.getFreq() != definitions.eRecurrence_YEARLY:
+                            rrule.setUseCount(True)
+                            rrule.setCount(maximumCount)
+                            rrules.changed()
                             changed = True
-                
-                if changed:
-                    master.setRRuleSet(rrules)
 
         return changed
 
@@ -903,7 +824,7 @@
         @return: the L{Component} for the new calendar with expanded instances.
         """
         
-        tzinfo = timezone.gettzinfo() if timezone else None
+        pytz = PyCalendarTimezone(timezone.getID()) if timezone else None
 
         # Create new calendar object with same properties as the original, but
         # none of the originals sub-components
@@ -918,7 +839,7 @@
         first = True
         for key in instances:
             instance = instances[key]
-            if timeRangesOverlap(instance.start, instance.end, start, end, tzinfo):
+            if timeRangesOverlap(instance.start, instance.end, start, end, pytz):
                 calendar.addComponent(self.expandComponent(instance, first))
             first = False
         
@@ -943,8 +864,8 @@
         # Convert all datetime properties to UTC unless they are floating
         for property in newcomp.properties():
             value = property.value()
-            if isinstance(value, datetime.datetime) and value.tzinfo is not None:
-                property.setValue(value.astimezone(utc))
+            if isinstance(value, PyCalendarDateTime) and value.local():
+                property.setValue(value.duplicateAsUTC())
         
         # Now reset DTSTART, DTEND/DURATION
         for property in newcomp.properties("DTSTART"):
@@ -1056,8 +977,7 @@
         if master:
             rrules = master.properties("RRULE")
             for rrule in rrules:
-                s = str(rrule)
-                if "COUNT" not in s and "UNTIL" not in s:
+                if not rrule.value().getUseCount() and not rrule.value().getUseUntil():
                     return True
         return False
         
@@ -1086,6 +1006,7 @@
         didCancel = False
         for exdate in tuple(master.properties("EXDATE")):
             for exdateValue in exdate.value():
+                exdateValue = exdateValue.getValue()
                 if exdateValue == rid:
                     if allowCancelled:
                         exdate.value().remove(exdateValue)
@@ -1104,13 +1025,13 @@
         # Check whether recurrence-id matches an RDATE - if so it is OK
         rdates = set()
         for rdate in master.properties("RDATE"):
-            rdates.update([asUTC(item) for item in rdate.value()])
+            rdates.update([item.getValue().duplicateAsUTC() for item in rdate.value()])
         if rid not in rdates:
             # Check whether we have a truncated RRULE
             rrules = master.properties("RRULE")
             if len(tuple(rrules)):
-                limit = rid
-                limit += datetime.timedelta(days=365)
+                limit = rid.duplicate()
+                limit += PyCalendarDuration(days=365)
                 instances = self.cacheExpandedTimeRanges(limit)
                 rids = set([instances[key].rid for key in instances])
                 instance_rid = normalizeForIndex(rid)
@@ -1135,23 +1056,16 @@
         if newcomp.hasProperty("DTEND"):
             dtend = newcomp.getProperty("DTEND")
             oldduration = dtend.value() - dtstart.value()
+        
+        newdtstartValue = rid.duplicate()
+        if dtstart.value().local():
+            newdtstartValue.adjustTimezone(dtstart.value().getTimezone())
             
-        if isinstance(dtstart.value(), datetime.datetime):
-            if dtstart.value().tzinfo:
-                newdtstartValue = rid.astimezone(dtstart.value().tzinfo)
-            else:
-                newdtstartValue = rid
-        else:
-            newdtstartValue = datetime.date.fromordinal(rid.toordinal())
-            
         dtstart.setValue(newdtstartValue)
         if newcomp.hasProperty("DTEND"):
             dtend.setValue(newdtstartValue + oldduration)
 
-        try:
-            rid_params = {"X-VOBJ-ORIGINAL-TZID":dtstart.params()["X-VOBJ-ORIGINAL-TZID"]}
-        except KeyError:
-            rid_params = {}
+        rid_params = {}
         newcomp.addProperty(Property("RECURRENCE-ID", dtstart.value(), params=rid_params))
         
         if didCancel:
@@ -1173,7 +1087,7 @@
         non_master_rids = [rid for rid in rids if rid is not None]
         if non_master_rids:
             highest_rid = max(non_master_rids)
-            self.cacheExpandedTimeRanges(highest_rid + datetime.timedelta(days=1))
+            self.cacheExpandedTimeRanges(highest_rid + PyCalendarDuration(days=1))
         for rid in rids:
             if self.validInstance(rid, clear_cache=False):
                 valid.add(rid)
@@ -1200,7 +1114,7 @@
             return False
 
         # Get expansion
-        instances = self.cacheExpandedTimeRanges(rid + datetime.timedelta(days=1))
+        instances = self.cacheExpandedTimeRanges(rid + PyCalendarDuration(days=1))
         new_rids = set([instances[key].rid for key in instances])
         return rid in new_rids
 
@@ -1375,28 +1289,23 @@
                 # If they're not both date or both date-time, raise error
                 if (subcomponent.hasProperty("DTSTART") and
                     subcomponent.hasProperty("RRULE")):
-                    dtValue = subcomponent.propertyNativeValue("DTSTART")
-                    dtType = type(dtValue)
+                    dtValue = subcomponent.propertyValue("DTSTART")
+                    dtutc = dtValue.duplicateAsUTC()
                     # Using properties("RRULE") rather than getRRuleSet() here
                     # because the dateutil rrule's _until values are datetime
                     # even if the UNTIL is a date (and therefore we can't
                     # check validity without doing the following):
-                    for rrule in subcomponent.properties("RRULE"):
-                        indexedTokens = {}
-                        indexedTokens.update([valuePart.split("=")
-                            for valuePart in rrule.value().split(";")])
-                        until = indexedTokens.get("UNTIL", None)
-                        if until:
-                            untilType = datetime.date if len(until) == 8 else datetime.datetime
-                            if untilType is not dtType:
+                    rrules = subcomponent._pycalendar.getRecurrenceSet()
+                    for rrule in rrules.getRules():
+                        if rrule.getUseUntil():
+                            if rrule.getUntil().isDateOnly() ^ dtValue.isDateOnly():
                                 msg = "Calendar resources must have matching type for DTSTART and UNTIL"
                                 log.debug(msg)
                                 if fix:
-                                    rrules = subcomponent.getRRuleSet()
-                                    if rrules:
-                                        log.debug("Fixing mismatch")
-                                        # vobject fixes DTSTART/UNTIL mismatches
-                                        subcomponent.setRRuleSet(rrules)
+                                    log.debug("Fixing mismatch")
+                                    rrule.getUntil().setDateOnly(dtValue.isDateOnly())
+                                    rrule.getUntil().setHHMMSS(dtutc.getHours(), dtutc.getMinutes(), dtutc.getSeconds())
+                                    rrules.changed()
                                 else:
                                     raise InvalidICalendarDataError(msg)
 
@@ -1461,31 +1370,6 @@
 
         return foundOrganizer
 
-    def transformAllFromNative(self):
-        self._vobject = self._vobject.transformFromNative()
-        self._vobject.transformChildrenFromNative(False)
-        
-    def transformAllToNative(self):
-        self._vobject = self._vobject.transformToNative()
-        self._vobject.transformChildrenToNative()
-
-    def gettzinfo(self):
-        """
-        Get the tzinfo for a Timezone component.
-
-        @return: L{datetime.tzinfo} if this is a VTIMEZONE, otherwise None.
-        """
-        if self.name() == "VTIMEZONE":
-            return self._vobject.gettzinfo()
-        elif self.name() == "VCALENDAR":
-            for component in self.subcomponents():
-                if component.name() == "VTIMEZONE":
-                    return component.gettzinfo()
-            else:
-                return None
-        else:
-            return None
-
     ##
     # iTIP stuff
     ##
@@ -1779,7 +1663,7 @@
                 continue
             for property in component.properties(propname):
                 if propvalue is None or property.value() == propvalue:
-                    property.params()[paramname] = [paramvalue]
+                    property.setParameter(paramname, paramvalue)
     
     def hasPropertyInAnyComponent(self, properties):
         """
@@ -1988,7 +1872,7 @@
                 remaining -= 1
                 continue
             rid = component.getRecurrenceIDUTC()
-            if (iCalendarString(rid) if rid else "") not in rids:
+            if (rid.getText() if rid else "") not in rids:
                 self.removeComponent(component)
                 remaining -= 1
                 
@@ -2064,7 +1948,7 @@
                 elif not xpname and remove_x_parameters:
                     for paramname in tuple(p.params()):
                         if paramname.startswith("X-"):
-                            del p.params()[paramname]
+                            p.removeParameter(paramname)
             
     def removePropertyParameters(self, property, params):
         """
@@ -2080,10 +1964,7 @@
             props = self.properties(property)
             for prop in props:
                 for param in params:
-                    try:
-                        del prop.params()[param]
-                    except KeyError:
-                        pass
+                    prop.removeParameter(param)
 
     def removePropertyParametersByValue(self, property, paramvalues):
         """
@@ -2099,14 +1980,7 @@
             props = self.properties(property)
             for prop in props:
                 for param, value in paramvalues:
-                    try:
-                        prop.params()[param].remove(value)
-                        if len(prop.params()[param]) == 0:
-                            del prop.params()[param]
-                    except KeyError:
-                        pass
-                    except InvalidICalendarDataError:
-                        pass
+                    prop.removeParameterValue(param, value)
 
     def normalizeAll(self):
         
@@ -2123,7 +1997,7 @@
             # Remove any default parameters
             for name, value in prop.params().items():
                 if value == [default_params.get(name),]:
-                    del prop.params()[name]
+                    prop.removeParameter(name)
             
             # If there are no parameters, remove the property if it has the default value
             if len(prop.params()) == 0:
@@ -2162,48 +2036,35 @@
             dtend = self.getProperty("DTEND")
             duration = self.getProperty("DURATION")
             
-            timeRange = timerange(
+            timeRange = PyCalendarPeriod(
                 start    = dtstart.value(),
                 end      = dtend.value()    if dtend is not None else None,
                 duration = duration.value() if duration is not None else None,
             )
 
-            dtstart.setValue(timeRange.start().asUTC().dateOrDatetime())
-            if "X-VOBJ-ORIGINAL-TZID" in dtstart.params():
-                dtstart.params()["ORIGINAL-TZID"] = dtstart.params()["X-VOBJ-ORIGINAL-TZID"]
-                del dtstart.params()["X-VOBJ-ORIGINAL-TZID"]
+            dtstart.setValue(timeRange.getStart().duplicateAsUTC())
             if dtend is not None:
-                dtend.setValue(timeRange.end().asUTC().dateOrDatetime())
-                if "X-VOBJ-ORIGINAL-TZID" in dtend.params():
-                    dtend.params()["ORIGINAL-TZID"] = dtend.params()["X-VOBJ-ORIGINAL-TZID"]
-                    del dtend.params()["X-VOBJ-ORIGINAL-TZID"]
+                dtend.setValue(timeRange.getEnd().duplicateAsUTC())
             elif duration is not None:
                 self.removeProperty(duration)
-                self.addProperty(Property("DTEND", timeRange.end().asUTC().dateOrDatetime()))
+                self.addProperty(Property("DTEND", timeRange.getEnd().duplicateAsUTC()))
 
             exdates = self.properties("EXDATE")
             for exdate in exdates:
-                exdate.setValue([asUTC(value) for value in exdate.value()])
-                try:
-                    del exdate.params()["TZID"]
-                except KeyError:
-                    pass
+                exdate.setValue([value.duplicateAsUTC() for value in exdate.value()])
+                exdate.removeParameter("TZID")
 
             rid = self.getProperty("RECURRENCE-ID")
             if rid is not None:
-                rid.setValue(asUTC(rid.value()))
-                try:
-                    del rid.params()["TZID"]
-                except KeyError:
-                    pass
+                rid.setValue(rid.value().duplicateAsUTC())
+                rid.removeProperty("TZID")
 
             # Recurrence rules - we need to normalize the order of the value parts
-            rrules = self.properties("RRULE")
-            for rrule in rrules:
-                indexedTokens = {}
-                indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().split(";")])
-                sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
-                rrule.setValue(sortedValue)
+#            for rrule in self._pycalendar.getRecurrenceSet().getRules():
+#                indexedTokens = {}
+#                indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().split(";")])
+#                sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
+#                rrule.setValue(sortedValue)
 
     def normalizePropertyValueLists(self, propname):
         """
@@ -2267,7 +2128,7 @@
                     continue
 
                 # Get any EMAIL parameter
-                oldemail = prop.params().get("EMAIL", (None,))[0]
+                oldemail = prop.paramsValue("EMAIL")
                 if oldemail:
                     oldemail = "mailto:%s" % (oldemail,)
 
@@ -2310,12 +2171,9 @@
 
                 # Always re-write the CN parameter
                 if name:
-                    prop.params()["CN"] = [name,]
+                    prop.setParameter("CN", name)
                 else:
-                    try:
-                        del prop.params()["CN"]
-                    except KeyError:
-                        pass
+                    prop.removeParameter("CN")
 
                 # Re-write the EMAIL if its value no longer matches
                 if oldemail and oldemail not in cuaddrs or oldemail is None and toUUID:
@@ -2330,12 +2188,9 @@
                             email = None
 
                     if email:
-                        prop.params()["EMAIL"] = [email,]
+                        prop.setParameter("EMAIL", email)
                     else:
-                        try:
-                            del prop.params()["EMAIL"]
-                        except KeyError:
-                            pass
+                        prop.removeParameter("EMAIL")
 
 
     def allPerUserUIDs(self):
@@ -2381,86 +2236,6 @@
         return tuple(results)
 
 ##
-# Dates and date-times
-##
-
-class FixedOffset (datetime.tzinfo):
-    """
-    Fixed offset in minutes east from UTC.
-    """
-    def __init__(self, offset, name=None):
-        self._offset = datetime.timedelta(minutes=offset)
-        self._name   = name
-
-    def utcoffset(self, dt): return self._offset
-    def tzname   (self, dt): return self._name
-    def dst      (self, dt): return datetime.timedelta(0)
-
-def parse_date(date_string):
-    """
-    Parse an iCalendar-format DATE string.  (RFC 2445, section 4.3.4)
-    @param date_string: an iCalendar-format DATE string.
-    @return: a L{datetime.date} object for the given C{date_string}.
-    """
-    try:
-        return stringToDate(date_string)
-    except (vParseError, InvalidICalendarDataError):
-        raise InvalidICalendarDataError("Invalid iCalendar DATE: %r" % (date_string,))
-
-def parse_time(time_string):
-    """
-    Parse iCalendar-format TIME string.  (RFC 2445, section 4.3.12)
-    @param time_string: an iCalendar-format TIME string.
-    @return: a L{datetime.time} object for the given C{time_string}.
-    """
-    try:
-        # Parse this as a fake date-time string by prepending date
-        with_date = "20000101T" + time_string
-        return stringToDateTime(with_date).time()
-    except (vParseError, InvalidICalendarDataError):
-        raise InvalidICalendarDataError("Invalid iCalendar TIME: %r" % (time_string,))
-
-def parse_datetime(datetime_string):
-    """
-    Parse iCalendar-format DATE-TIME string.  (RFC 2445, section 4.3.5)
-    @param datetime_string: an iCalendar-format DATE-TIME string.
-    @return: a L{datetime.datetime} object for the given C{datetime_string}.
-    """
-    try:
-        return stringToDateTime(datetime_string)
-    except (vParseError, InvalidICalendarDataError):
-        raise InvalidICalendarDataError("Invalid iCalendar DATE-TIME: %r" % (datetime_string,))
-
-def parse_date_or_datetime(date_string):
-    """
-    Parse iCalendar-format DATE or DATE-TIME string.  (RFC 2445, sections 4.3.4
-    and 4.3.5)
-    @param date_string: an iCalendar-format DATE or DATE-TIME string.
-    @return: a L{datetime.date} or L{datetime.datetime} object for the given
-        C{date_string}.
-    """
-    try:
-        if len(date_string) == 8:
-            return parse_date(date_string)
-        else:
-            return parse_datetime(date_string)
-    except InvalidICalendarDataError:
-        raise InvalidICalendarDataError("Invalid iCalendar DATE or DATE-TIME: %r" % (date_string,))
-
-def parse_duration(duration_string):
-    """
-    Parse iCalendar-format DURATION string.  (RFC 2445, sections 4.3.6)
-    @param duration_string: an iCalendar-format DURATION string.
-    @return: a L{datetime.timedelta} object for the given C{duration_string}.
-    """
-    try:
-        return stringToDurations(duration_string)[0]
-    except (vParseError, InvalidICalendarDataError):
-        raise InvalidICalendarDataError("Invalid iCalendar DURATION: %r" % (duration_string,))
-
-_regex_duration = None
-
-##
 # Timezones
 ##
 

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,19 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.period import PyCalendarPeriod
+from pycalendar.timezone import PyCalendarTimezone
 
 """
 iCalendar Recurrence Expansion Utilities
 """
 
-import datetime
+from twistedcaldav.dateops import normalizeForIndex, differenceDateTime
 
-from vobject.icalendar import utc
-
-from twext.python.datetime import dateordatetime
-
-from twistedcaldav.dateops import normalizeForIndex, differenceDateTime, periodEnd
-
 # The maximum number of instances we will expand out to.
 # Raise a TooManyInstancesError exception if we exceed this.
 max_allowed_instances = 1000
@@ -48,22 +46,11 @@
 
 class Instance(object):
     
-    __slots__ = ["component", "start", "end", "rid", "overridden", "future"]
-    
     def __init__(self, component, start = None, end = None, rid = None, overridden = False, future = False):
         self.component = component
-        if start is None:
-            self.start = component.getStartDateUTC()
-        else:
-            self.start = start
-        if end is None:
-            self.end = component.getEndDateUTC()
-        else:
-            self.end = end
-        if rid is None:
-            self.rid = self.start
-        else:
-            self.rid = rid
+        self.start = component.getStartDateUTC() if start is None else start
+        self.end = component.getEndDateUTC() if end is None else end
+        self.rid = self.start if rid is None else rid
         self.overridden = overridden
         self.future = future
         
@@ -78,15 +65,12 @@
             (trigger, related, repeat, duration)  = alarm.getTriggerDetails()
             
             # Handle relative vs absolute triggers
-            if isinstance(trigger, datetime.date):
+            if isinstance(trigger, PyCalendarDateTime):
                 # Absolute trigger
                 start = trigger
             else:
                 # Relative trigger
-                if related:
-                    start = self.start + trigger
-                else:
-                    start = self.end + trigger
+                start = (self.start if related else self.end) + trigger
             triggers.add(start)
             
             # Handle repeats
@@ -98,8 +82,6 @@
     
 class InstanceList(object):
     
-    __slots__ = ["instances", "limit", "ignoreInvalidInstances",]
-    
     def __init__(self, ignoreInvalidInstances=False):
         self.instances = {}
         self.limit = None
@@ -194,12 +176,12 @@
         end = component.getEndDateUTC()
         duration = None
         if end is None:
-            if isinstance(start, datetime.datetime):
+            if not start.isDateOnly():
                 # Timed event with zero duration
-                duration = datetime.timedelta(days=0)
+                duration = PyCalendarDuration(days=0)
             else:
                 # All day event default duration is one day
-                duration = datetime.timedelta(days=1)
+                duration = PyCalendarDuration(days=1)
             end = start + duration
         else:
             duration = differenceDateTime(start, end)
@@ -223,15 +205,13 @@
         end = component.getEndDateUTC()
         duration = None
         if end is None:
-            if isinstance(start, datetime.datetime):
+            if not start.isDateOnly():
                 # Timed event with zero duration
-                duration = datetime.timedelta(days=0)
+                duration = PyCalendarDuration(days=0)
             else:
                 # All day event default duration is one day
-                duration = datetime.timedelta(days=1)
+                duration = PyCalendarDuration(days=1)
             end = start + duration
-        else:
-            duration = differenceDateTime(start, end)
 
         self._addOverrideComponent(component, limit, start, end, got_master)
 
@@ -280,34 +260,26 @@
         self._addOverrideComponent(component, limit, start, due, got_master)
 
     def _addMasterComponent(self, component, limit, start, end, duration):
-        # Always add first instance if included in range.
-        if dateordatetime(start) < limit:
-            # dateutils does not do all-day - so convert to datetime.datetime
-            start = normalizeForIndex(start)
-            end = normalizeForIndex(end)
-            
-            # Do not add if in EXDATEs
-            exdates = []
-            for prop in component.properties("EXDATE"):
-                exdates.extend(prop.value())
-            exdates = [normalizeForIndex(exdate) for exdate in exdates]
-            if start not in exdates:
-                self.addInstance(Instance(component, start, end))
-        else:
-            self.limit = limit
         
-        # Now expand recurrence
-        # FIXME: Current Python implementation fails when RDATEs are PERIODs
-        recur = component.getRRuleSet(True)
-        if recur is not None:
-            for startDate in recur:
-                if dateordatetime(startDate) >= limit:
-                    self.limit = limit
-                    break
-                endDate = startDate + duration
+        rrules = component.getRecurrenceSet()
+        if rrules is not None:
+            # Do recurrence set expansion
+            expanded = []
+            limited = rrules.expand(start, PyCalendarPeriod(start, limit), expanded)
+            for startDate in expanded:
                 startDate = normalizeForIndex(startDate)
-                endDate = normalizeForIndex(endDate)
+                endDate = startDate + duration
                 self.addInstance(Instance(component, startDate, endDate))
+            if limited:
+                self.limit = limit
+        else:
+            # Always add main instance if included in range.
+            if start < limit:
+                start = normalizeForIndex(start)
+                end = normalizeForIndex(end)
+                self.addInstance(Instance(component, start, end))
+            else:
+                self.limit = limit
     
     def _addOverrideComponent(self, component, limit, start, end, got_master):
 
@@ -321,12 +293,12 @@
         rid = normalizeForIndex(rid)
 
         # Make sure start is within the limit
-        if dateordatetime(start) > limit and dateordatetime(rid) > limit:
+        if start > limit and rid > limit:
             return
 
         # Make sure override RECURRENCE-ID is a valid instance of the master
         if got_master:
-            if str(rid) not in self.instances and dateordatetime(rid) < limit:
+            if str(rid) not in self.instances and rid < limit:
                 if self.ignoreInvalidInstances:
                     return
                 else:
@@ -375,7 +347,7 @@
         """
 
         start = component.getStartDateUTC()
-        if start is not None and dateordatetime(start) >= limit:
+        if start is not None and start >= limit:
             # If the free busy is beyond the end of the range we want, ignore it
             return
 
@@ -389,10 +361,10 @@
             assert isinstance(fb.value(), list), "FREEBUSY property does not contain a list of values: %r" % (fb,)
             for period in fb.value():
                 # Ignore if period starts after limit
-                if dateordatetime(period[0]) >= limit:
+                if period.getStart() >= limit:
                     continue
-                start = normalizeForIndex(period[0])
-                end = normalizeForIndex(periodEnd(period))
+                start = normalizeForIndex(period.getStart())
+                end = normalizeForIndex(period.getEnd())
                 self.addInstance(Instance(component, start, end))
 
     def _addAvailabilityComponent(self, component, limit):
@@ -407,16 +379,16 @@
         """
 
         start = component.getStartDateUTC()
-        if start is not None and dateordatetime(start) >= limit:
+        if start is not None and start >= limit:
             # If the free busy is beyond the end of the range we want, ignore it
             return
         if start is None:
-            start = datetime.datetime(1900, 1, 1, 0, 0, 0, tzinfo=utc)
+            start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
         start = normalizeForIndex(start)
 
         end = component.getEndDateUTC()
         if end is None:
-            end = datetime.datetime(3000, 1, 1, 0, 0, 0, tzinfo=utc)
+            end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
         end = normalizeForIndex(end)
 
         self.addInstance(Instance(component, start, end))

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ##
+from pycalendar.datetime import PyCalendarDateTime
 
 """
 Object model of CALDAV:filter element used in a calendar-query.
@@ -26,7 +27,7 @@
 
 from twistedcaldav.caldavxml import caldav_namespace, CalDAVTimeZoneElement
 from twistedcaldav.dateops import timeRangesOverlap
-from twistedcaldav.ical import Component, Property, parse_date_or_datetime
+from twistedcaldav.ical import Component, Property
 from vobject.icalendar import utc
 import datetime
 
@@ -552,8 +553,8 @@
         if "start" not in xml_element.attributes and "end" not in xml_element.attributes:
             raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
         
-        self.start = parse_date_or_datetime(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
-        self.end = parse_date_or_datetime(xml_element.attributes["end"]) if "end" in xml_element.attributes else None
+        self.start = PyCalendarDateTime.parseText(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
+        self.end = PyCalendarDateTime.parseText(xml_element.attributes["end"]) if "end" in xml_element.attributes else None
         self.tzinfo = None
 
     def settzinfo(self, tzinfo):

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -15,7 +15,7 @@
 ##
 
 from twext.python.log import Logger
-from twext.python.datetime import timerange, asUTC, iCalendarString
+#from twext.python.datetime import timerange, asUTC, iCalendarString
 
 from twistedcaldav.config import config
 from twistedcaldav.ical import Component, Property

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -36,7 +36,7 @@
 from vobject.icalendar import dateTimeToString
 
 from twext.python.log import Logger
-from twext.python.datetime import asUTC, iCalendarString
+#from twext.python.datetime import asUTC, iCalendarString
 
 from twistedcaldav.config import config
 from twistedcaldav.ical import Property, iCalendarProductID, Component

Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py	2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py	2011-03-01 20:28:29 UTC (rev 7090)
@@ -15,19 +15,18 @@
 ##
 
 import os
-import datetime
-from dateutil.tz import tzutc
 from difflib import unified_diff
 import itertools
 
 from twisted.trial.unittest import SkipTest
 
-from twistedcaldav.ical import Component, parse_date, parse_datetime,\
-    parse_date_or_datetime, parse_duration, Property, InvalidICalendarDataError
+from twistedcaldav.ical import Component, Property, InvalidICalendarDataError
 from twistedcaldav.instance import InvalidOverriddenInstanceError
 import twistedcaldav.test.util
 
-from vobject.icalendar import utc
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.duration import PyCalendarDuration
 
 class iCalendar (twistedcaldav.test.util.TestCase):
     """
@@ -186,13 +185,13 @@
 
         year = 2004
 
-        instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
-            self.assertEqual(start, datetime.datetime(year, 7, 4))
-            self.assertEqual(end  , datetime.datetime(year, 7, 5))
+            self.assertEqual(start, PyCalendarDateTime(year, 7, 4))
+            self.assertEqual(end  , PyCalendarDateTime(year, 7, 5))
             if year == 2050: break
             year += 1
 
@@ -211,14 +210,14 @@
         }
         year = 2004
 
-        instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
             if year in results:
-                self.assertEqual(start, datetime.datetime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , datetime.datetime(year, results[year][0], results[year][2]))
+                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
             if year == 2050: break
             year += 1
 
@@ -237,14 +236,14 @@
         }
         year = 2002
 
-        instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
             if year in results:
-                self.assertEqual(start, datetime.datetime(year, results[year][0], results[year][1]))
-                self.assertEqual(end  , datetime.datetime(year, results[year][0], results[year][2]))
+                self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
+                self.assertEqual(end  , PyCalendarDateTime(year, results[year][0], results[year][2]))
             if year == 2050: break
             year += 1
 
@@ -256,13 +255,13 @@
         """
         calendar = Component.fromStream(file(os.path.join(self.data_dir, "Holidays", "C318ABFE-1ED0-11D9-A5E0-000A958A3252.ics")))
 
-        instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+        instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
         for key in instances:
             instance = instances[key]
             start = instance.start
             end = instance.end
-            self.assertEqual(start, datetime.datetime(2004, 11, 25))
-            self.assertEqual(end, datetime.datetime(2004, 11, 27))
+            self.assertEqual(start, PyCalendarDateTime(2004, 11, 25))
+            self.assertEqual(end, PyCalendarDateTime(2004, 11, 27))
             break;
 
     #test_component_timerange.todo = "recurrence expansion should give us no end date here"
@@ -271,49 +270,41 @@
         """
         parse_date()
         """
-        self.assertEqual(parse_date("19970714"), datetime.date(1997, 7, 14))
+        self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
 
     def test_parse_datetime(self):
         """
         parse_datetime()
         """
-        try: parse_datetime("19980119T2300")
-        except ValueError: pass
-        else: self.fail("Invalid DATE-TIME should raise ValueError")
+        dt = PyCalendarDateTime.parseText("19980118T230000")
+        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+        self.assertTrue(dt.floating())
 
-        dt = parse_datetime("19980118T230000")
-        self.assertEqual(dt, datetime.datetime(1998, 1, 18, 23, 0))
-        self.assertNot(dt.tzinfo)
+        dt = PyCalendarDateTime.parseText("19980119T070000Z")
+        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
 
-        dt = parse_datetime("19980119T070000Z")
-        self.assertEqual(dt, datetime.datetime(1998, 1, 19, 07, 0, tzinfo=utc))
-
     def test_parse_date_or_datetime(self):
         """
         parse_date_or_datetime()
         """
-        self.assertEqual(parse_date_or_datetime("19970714"), datetime.date(1997, 7, 14))
+        self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
 
-        try: parse_date_or_datetime("19980119T2300")
-        except ValueError: pass
-        else: self.fail("Invalid DATE-TIME should raise ValueError")
+        dt = PyCalendarDateTime.parseText("19980118T230000")
+        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+        self.assertTrue(dt.floating())
 
-        dt = parse_date_or_datetime("19980118T230000")
-        self.assertEqual(dt, datetime.datetime(1998, 1, 18, 23, 0))
-        self.assertNot(dt.tzinfo)
+        dt = PyCalendarDateTime.parseText("19980119T070000Z")
+        self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
 
-        dt = parse_date_or_datetime("19980119T070000Z")
-        self.assertEqual(dt, datetime.datetime(1998, 1, 19, 07, 0, tzinfo=utc))
-
     def test_parse_duration(self):
         """
         parse_duration()
         """
-        self.assertEqual(parse_duration( "P15DT5H0M20S"), datetime.timedelta(days= 15, hours= 5, minutes=0, seconds= 20))
-        self.assertEqual(parse_duration("+P15DT5H0M20S"), datetime.timedelta(days= 15, hours= 5, minutes=0, seconds= 20))
-        self.assertEqual(parse_duration("-P15DT5H0M20S"), datetime.timedelta(days=-15, hours=-5, minutes=0, seconds=-20))
+        self.assertEqual(PyCalendarDuration.parseText( "P15DT5H0M20S"), PyCalendarDuration(days= 15, hours= 5, minutes=0, seconds= 20))
+        self.assertEqual(PyCalendarDuration.parseText("+P15DT5H0M20S"), PyCalendarDuration(days= 15, hours= 5, minutes=0, seconds= 20))
+        self.assertEqual(PyCalendarDuration.parseText("-P15DT5H0M20S"), PyCalendarDuration(days=-15, hours=-5, minutes=0, seconds=-20))
 
-        self.assertEqual(parse_duration("P7W"), datetime.timedelta(weeks=7))
+        self.assertEqual(PyCalendarDuration.parseText("P7W"), PyCalendarDuration(weeks=7))
 
     def test_correct_attendee_properties(self):
         
@@ -413,7 +404,7 @@
 """,
                 (
                     ("mailto:user1 at example.com", None),
-                    ("mailto:user1 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc()))
+                    ("mailto:user1 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
                 )
             ),
             (
@@ -437,7 +428,7 @@
 """,
                 (
                     ("mailto:user1 at example.com", None),
-                    ("mailto:user3 at example.com", datetime.datetime(2009, 11, 14, 0, 0, tzinfo=tzutc()))
+                    ("mailto:user3 at example.com", PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
                 )
             ),
             (
@@ -542,8 +533,8 @@
                 False,
                 (
                     ("mailto:user2 at example.com", None),
-                    ("mailto:user2 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc())),
-                    ("mailto:user3 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc()))
+                    ("mailto:user2 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+                    ("mailto:user3 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
                 )
             ),
             (
@@ -798,7 +789,7 @@
 
         for original, result in data:
             component = Component.fromString(original)
-            component.addPropertyToAllComponents(Property("REQUEST-STATUS", ["2.0", "Success"]))
+            component.addPropertyToAllComponents(Property("REQUEST-STATUS", "2.0;Success"))
             self.assertEqual(result, str(component).replace("\r", ""))        
 
     def test_attendees_views(self):
@@ -1751,7 +1742,7 @@
 END:VCALENDAR
 """,
                 False,
-                (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),)
+                (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),)
             ),
             (
                 "Simple recurring",
@@ -1768,8 +1759,8 @@
 """,
                 False,
                 (
-                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
             (
@@ -1788,9 +1779,9 @@
 """,
                 False,
                 (
-                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 16, 1, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
             (
@@ -1809,8 +1800,8 @@
 """,
                 False,
                 (
-                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
             (
@@ -1829,8 +1820,8 @@
 """,
                 False,
                 (
-                    datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
             (
@@ -1854,8 +1845,8 @@
 """,
                 False,
                 (
-                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
             (
@@ -1901,8 +1892,8 @@
 """,
                 True,
                 (
-                    datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 )
             ),
         )
@@ -1910,9 +1901,9 @@
         for description, original, ignoreInvalidInstances, results in data:
             component = Component.fromString(original)
             if results is None:
-                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, datetime.date(2100, 1, 1), ignoreInvalidInstances)
+                self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances)
             else:
-                instances = component.expandTimeRanges(datetime.date(2100, 1, 1), ignoreInvalidInstances)
+                instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances)
                 self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
                 for instance in instances:
                     self.assertTrue(instances[instance].start in results, "%s: %s missing" % (description, instance,))
@@ -2631,7 +2622,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 2, 8, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T080000Z
@@ -2654,7 +2645,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 2, 18, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090102T180000Z
@@ -2678,7 +2669,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 3, 18, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID:20090103T180000Z
@@ -2700,7 +2691,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 2, 9, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 None,
             ),
             (
@@ -2717,7 +2708,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 2, 19, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 None,
             ),
             (
@@ -2735,7 +2726,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 3, 19, 0, 0, tzinfo=tzutc()),
+                PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 None,
             ),
             (
@@ -2751,7 +2742,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.date(2009, 1, 8),
+                PyCalendarDateTime(2009, 1, 8),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090108
@@ -2774,7 +2765,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.date(2009, 1, 3),
+                PyCalendarDateTime(2009, 1, 3),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090103
@@ -2798,7 +2789,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.date(2009, 1, 10),
+                PyCalendarDateTime(2009, 1, 10),
                 """BEGIN:VEVENT
 UID:12345-67890-1
 RECURRENCE-ID;VALUE=DATE:20090110
@@ -2820,7 +2811,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.date(2009, 1, 3),
+                PyCalendarDateTime(2009, 1, 3),
                 None,
             ),
             (
@@ -2837,7 +2828,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.date(2009, 1, 5),
+                PyCalendarDateTime(2009, 1, 5),
                 None,
             ),
             (
@@ -2855,7 +2846,7 @@
 END:VEVENT
 END:VCALENDAR
 """,
-                datetime.datetime(2009, 1, 19),
+                PyCalendarDateTime(2009, 1, 19),
                 None,
             ),
         )
@@ -2885,8 +2876,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 2, 8, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 4, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -2920,8 +2911,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 2, 18, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 4, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -2956,8 +2947,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 3, 18, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 5, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 5, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     """BEGIN:VEVENT
@@ -2990,8 +2981,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 2, 9, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     None,
@@ -3019,8 +3010,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 2, 19, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     None,
@@ -3049,8 +3040,8 @@
 END:VCALENDAR
 """,
                 (
-                    datetime.datetime(2009, 1, 3, 19, 0, 0, tzinfo=tzutc()),
-                    datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+                    PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+                    PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                 ),
                 (
                     None,
@@ -3234,8 +3225,8 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3252,9 +3243,9 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 5, 0, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 5, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3271,10 +3262,10 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3292,11 +3283,11 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 2, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3315,12 +3306,12 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 2, 0, 0, tzinfo=tzutc()), False),
-                    (datetime.datetime(2009, 10, 3, 0, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (PyCalendarDateTime(2009, 10, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3342,11 +3333,11 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()), False),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3369,12 +3360,12 @@
 """,
                 (
                     (None, True),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2007, 11, 15, 2, 0, 0, tzinfo=tzutc()), False),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3391,9 +3382,9 @@
 """,
                 (
                     (None, False),
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), False),
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
-                    (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+                    (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
             (
@@ -3423,7 +3414,7 @@
 END:VCALENDAR
 """,
                 (
-                    (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
+                    (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
                 )
             ),
             (
@@ -3438,7 +3429,7 @@
 END:VCALENDAR
 """,
                 (
-                    (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), False),
+                    (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
                 )
             ),
         )
@@ -3727,7 +3718,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                 ),
@@ -3771,7 +3762,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -3824,7 +3815,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -3868,19 +3859,19 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", True,),
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", True,),
                                 ),
@@ -3941,21 +3932,21 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
@@ -4038,7 +4029,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
@@ -4046,7 +4037,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", True,),
@@ -4054,7 +4045,7 @@
                                 ),
                             ),
                             (
-                                datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+                                PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
                                 (
                                     ("", False,),
                                     ("user01", False,),
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110301/e7440aa9/attachment-0001.html>


More information about the calendarserver-changes mailing list