# HG changeset patch # User Paul Boddie # Date 1431878346 -7200 # Node ID a5e8c1027e599d1be6fdb098bfb9de59a00553e5 # Parent 171fa53430a7230b323dd3d87303025279e2c6b4 Introduced a time zone context into period instances. diff -r 171fa53430a7 -r a5e8c1027e59 imiptools/data.py --- a/imiptools/data.py Sun May 17 17:16:23 2015 +0200 +++ b/imiptools/data.py Sun May 17 17:59:06 2015 +0200 @@ -411,8 +411,8 @@ "A period with origin information from the object." - def __init__(self, start, end, origin, start_attr=None, end_attr=None): - Period.__init__(self, start, end, origin) + def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None): + Period.__init__(self, start, end, tzid, origin) self.start_attr = start_attr self.end_attr = end_attr @@ -423,13 +423,13 @@ return self.end, self.end_attr def get_tzid(self): - return get_tzid(self.start_attr, self.end_attr) + return get_tzid(self.start_attr, self.end_attr) or self.tzid def as_tuple(self): - return self.start, self.end, self.origin, self.start_attr, self.end_attr + return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr def __repr__(self): - return "RecurringPeriod(%r, %r, %r, %r, %r)" % (self.start, self.end, self.origin, self.start_attr, self.end_attr) + return "RecurringPeriod(%r)" % (self.as_tuple(),) def get_periods(obj, tzid, window_end, inclusive=False): @@ -458,7 +458,7 @@ tzid = get_tzid(dtstart_attr, dtend_attr) or tzid if not rrule: - periods = [RecurringPeriod(dtstart, dtend, "DTSTART", dtstart_attr, dtend_attr)] + periods = [RecurringPeriod(dtstart, dtend, tzid, "DTSTART", dtstart_attr, dtend_attr)] else: # Recurrence rules create multiple instances to be checked. # Conflicts may only be assessed within a period defined by policy @@ -477,7 +477,7 @@ for start in selector.materialise(dtstart, window_end, parameters.get("COUNT"), parameters.get("BYSETPOS"), inclusive): start = to_timezone(datetime(*start), tzid) end = start + duration - periods.append(RecurringPeriod(start, end, "RRULE")) + periods.append(RecurringPeriod(start, end, tzid, "RRULE")) # Add recurrence dates. @@ -486,9 +486,9 @@ if rdates: for rdate, rdate_attr in rdates: if isinstance(rdate, tuple): - periods.append(RecurringPeriod(rdate[0], rdate[1], "RDATE", rdate_attr)) + periods.append(RecurringPeriod(rdate[0], rdate[1], tzid, "RDATE", rdate_attr)) else: - periods.append(RecurringPeriod(rdate, rdate + duration, "RDATE", rdate_attr)) + periods.append(RecurringPeriod(rdate, rdate + duration, tzid, "RDATE", rdate_attr)) # Return a sorted list of the periods. diff -r 171fa53430a7 -r a5e8c1027e59 imiptools/period.py --- a/imiptools/period.py Sun May 17 17:16:23 2015 +0200 +++ b/imiptools/period.py Sun May 17 17:59:06 2015 +0200 @@ -23,26 +23,42 @@ from datetime import date, datetime, timedelta from imiptools.dates import format_datetime, get_datetime, \ get_datetime_attributes, \ - get_start_of_day, to_timezone + get_start_of_day, to_timezone, to_utc_datetime class Period: "A basic period abstraction." - def __init__(self, start, end, origin=None): + def __init__(self, start, end, tzid=None, origin=None): + + """ + Initialise a period with the given 'start' and 'end', having a + contextual 'tzid', if specified, and an indicated 'origin'. + """ + self.start = isinstance(start, date) and start or get_datetime(start) self.end = isinstance(end, date) and end or get_datetime(end) + self.tzid = tzid self.origin = origin def as_tuple(self): - return self.start, self.end + return self.start, self.end, self.tzid, self.origin def __hash__(self): return hash((self.get_start(), self.get_end())) def __cmp__(self, other): + + """ + Return a comparison result against 'other' using points in time, + employing the time zone context to convert dates. + """ + if isinstance(other, Period): - return cmp((self.get_start(), self.get_end()), (other.get_start(), other.get_end())) + return cmp( + (to_utc_datetime(self.get_start(), self.get_tzid()), to_utc_datetime(self.get_end(), self.get_tzid())), + (to_utc_datetime(other.get_start(), self.get_tzid()), to_utc_datetime(other.get_end(), self.get_tzid())) + ) else: return 1 @@ -50,7 +66,7 @@ return self.get_start(), self.get_end() def __repr__(self): - return "Period(%r, %r)" % (self.start, self.end) + return "Period(%r)" % (self.as_tuple(),) # Datetime metadata methods. @@ -60,6 +76,9 @@ def get_end(self): return self.end + def get_tzid(self): + return self.tzid + def get_start_item(self): return self.start, get_datetime_attributes(self.start) @@ -70,15 +89,15 @@ "A free/busy record abstraction." - def __init__(self, start, end, uid=None, transp=None, recurrenceid=None, summary=None, organiser=None): + def __init__(self, start, end, uid=None, transp=None, recurrenceid=None, summary=None, organiser=None, tzid=None): """ - Initialise a free/busy period with 'start' and 'end' datetime string - representations, employing UTC, plus any 'uid', 'transp', - 'recurrenceid', 'summary' and 'organiser' details. + Initialise a free/busy period with the given 'start' and 'end' limits, + with an optional 'tzid', plus any 'uid', 'transp', 'recurrenceid', + 'summary' and 'organiser' details. """ - Period.__init__(self, start, end) + Period.__init__(self, start, end, tzid) self.uid = uid self.transp = transp self.recurrenceid = recurrenceid @@ -89,18 +108,23 @@ return format_datetime(self.start), format_datetime(self.end), self.uid, self.transp, self.recurrenceid, self.summary, self.organiser def __cmp__(self, other): - if isinstance(other, FreeBusyPeriod): - return cmp((self.get_start(), self.get_end(), self.uid), (other.get_start(), other.get_end(), other.uid)) + + """ + Compare this object to 'other', employing the uid if the periods + involved are the same. + """ + + result = Period.__cmp__(self, other) + if result == 0 and isinstance(other, FreeBusyPeriod): + return cmp(self.uid, other.uid) else: - return Period.__cmp__(self, other) + return result def get_key(self): - return self.uid, self.recurrenceid, self.start + return self.uid, self.recurrenceid, self.get_start() def __repr__(self): - return "FreeBusyPeriod(%r, %r, %r, %r, %r, %r, %r)" % ( - self.start, self.end, self.uid, self.transp, self.recurrenceid, - self.summary, self.organiser) + return "FreeBusyPeriod(%r)" % (self.as_tuple(),) # Time and period management. diff -r 171fa53430a7 -r a5e8c1027e59 imipweb/data.py --- a/imipweb/data.py Sun May 17 17:16:23 2015 +0200 +++ b/imipweb/data.py Sun May 17 17:59:06 2015 +0200 @@ -36,7 +36,7 @@ intended to represent information obtained from an iCalendar resource. """ - def __init__(self, start, end, start_attr=None, end_attr=None, form_start=None, form_end=None, origin=None): + def __init__(self, start, end, tzid=None, origin=None, start_attr=None, end_attr=None, form_start=None, form_end=None): """ Initialise a period with the given 'start' and 'end' datetimes, together @@ -45,15 +45,15 @@ 'origin' indicating the kind of period this object describes. """ - RecurringPeriod.__init__(self, start, end, origin, start_attr, end_attr) + RecurringPeriod.__init__(self, start, end, tzid, origin, start_attr, end_attr) self.form_start = form_start self.form_end = form_end def as_tuple(self): - return self.start, self.end, self.start_attr, self.end_attr, self.form_start, self.form_end, self.origin + return self.start, self.end, self.tzid, self.origin, self.start_attr, self.end_attr, self.form_start, self.form_end def __repr__(self): - return "EventPeriod(%r, %r, %r, %r, %r, %r, %r)" % self.as_tuple() + return "EventPeriod(%r)" % (self.as_tuple(),) def as_event_period(self): return self @@ -76,6 +76,7 @@ self.get_form_end(), isinstance(self.end, datetime) or self.get_start() != self.get_end(), isinstance(self.start, datetime) or isinstance(self.end, datetime), + self.tzid, self.origin ) @@ -93,18 +94,19 @@ "A period whose information originates from a form." - def __init__(self, start, end, end_enabled=True, times_enabled=True, origin=None): + def __init__(self, start, end, end_enabled=True, times_enabled=True, tzid=None, origin=None): self.start = start self.end = end self.end_enabled = end_enabled self.times_enabled = times_enabled + self.tzid = tzid self.origin = origin def as_tuple(self): - return self.start, self.end, self.end_enabled, self.times_enabled, self.origin + return self.start, self.end, self.end_enabled, self.times_enabled, self.tzid, self.origin def __repr__(self): - return "FormPeriod(%r, %r, %r, %r, %r)" % self.as_tuple() + return "FormPeriod(%r)" % (self.as_tuple(),) def _get_start(self): return self.start.as_datetime(self.times_enabled), self.start.get_attributes(self.times_enabled) @@ -158,7 +160,7 @@ index is not None and ("dtend", index) or "dtend" ]) - return EventPeriod(dtstart, end_date_to_calendar(dtend), dtstart_attr, dtend_attr, self.start, self.end, self.origin) + return EventPeriod(dtstart, end_date_to_calendar(dtend), self.origin, self.tzid, dtstart_attr, dtend_attr, self.start, self.end) # Period data methods. @@ -204,7 +206,7 @@ return self.date, self.hour, self.minute, self.second, self.tzid, self.dt, self.attr def __repr__(self): - return "FormDate(%r, %r, %r, %r, %r, %r, %r)" % self.as_tuple() + return "FormDate(%r)" % (self.as_tuple(),) def get_component(self, value): return (value or "").rjust(2, "0")[:2] @@ -292,7 +294,7 @@ dtend, dtend_attr = period.get_end_item() if not isinstance(period, RecurringPeriod): dtend = end_date_to_calendar(dtend) - return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr, origin=period.origin) + return EventPeriod(dtstart, dtend, period.tzid, period.origin, dtstart_attr, dtend_attr) def form_period_from_period(period): if isinstance(period, EventPeriod): diff -r 171fa53430a7 -r a5e8c1027e59 imipweb/event.py --- a/imipweb/event.py Sun May 17 17:16:23 2015 +0200 +++ b/imipweb/event.py Sun May 17 17:59:06 2015 +0200 @@ -334,7 +334,7 @@ else: dtend, dtend_attr = dtstart, dtstart_attr - return EventPeriod(dtstart, dtend, dtstart_attr, dtend_attr) + return EventPeriod(dtstart, dtend, self.get_tzid(), None, dtstart_attr, dtend_attr) def get_main_period(self): @@ -347,7 +347,7 @@ start = self.get_date_control_values("dtstart") end = self.get_date_control_values("dtend") - return FormPeriod(start, end, dtend_enabled, dttimes_enabled) + return FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid()) def get_current_recurrences(self, obj): @@ -393,7 +393,7 @@ dtend_enabled = str(index) in all_dtend_enabled dttimes_enabled = str(index) in all_dttimes_enabled - period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, origin) + period = FormPeriod(start, end, dtend_enabled, dttimes_enabled, self.get_tzid(), origin) periods.append(period) return periods diff -r 171fa53430a7 -r a5e8c1027e59 imipweb/resource.py --- a/imipweb/resource.py Sun May 17 17:16:23 2015 +0200 +++ b/imipweb/resource.py Sun May 17 17:59:06 2015 +0200 @@ -147,7 +147,8 @@ obj.get_value("TRANSP"), recurrenceid, obj.get_value("SUMMARY"), - obj.get_value("ORGANIZER") + obj.get_value("ORGANIZER"), + self.get_tzid() )) return summary