2.1 --- a/imip_manager.py Tue Feb 03 00:02:18 2015 +0100
2.2 +++ b/imip_manager.py Tue Feb 03 00:33:45 2015 +0100
2.3 @@ -33,9 +33,9 @@
2.4 from imiptools.content import Handler
2.5 from imiptools.data import get_address, get_uri, make_freebusy, parse_object, \
2.6 Object, to_part
2.7 -from imiptools.dates import format_datetime, get_datetime, get_start_of_day, \
2.8 - get_end_of_day, get_timestamp, ends_on_same_day, \
2.9 - to_timezone
2.10 +from imiptools.dates import format_datetime, get_datetime, get_datetime_item, \
2.11 + get_start_of_day, get_start_of_next_day, get_timestamp, \
2.12 + ends_on_same_day, to_timezone
2.13 from imiptools.mail import Messenger
2.14 from imiptools.period import add_day_start_points, add_slots, convert_periods, \
2.15 get_freebusy_details, \
2.16 @@ -401,6 +401,12 @@
2.17 for i, (start, end) in enumerate(coalesced):
2.18 this_uid = "%s-%s" % (uid, i)
2.19
2.20 + start = get_datetime(start, {"TZID" : tzid})
2.21 + end = end and get_datetime(end, {"TZID" : tzid}) or get_start_of_next_day(start, tzid)
2.22 +
2.23 + start_value, start_attr = get_datetime_item(start)
2.24 + end_value, end_attr = get_datetime_item(end)
2.25 +
2.26 # Create a calendar object and store it as a request.
2.27
2.28 record = []
2.29 @@ -409,10 +415,8 @@
2.30 rwrite(("UID", {}, this_uid))
2.31 rwrite(("SUMMARY", {}, "New event at %s" % utcnow))
2.32 rwrite(("DTSTAMP", {}, utcnow))
2.33 - rwrite(("DTSTART", {"VALUE" : "DATE-TIME", "TZID" : tzid}, start))
2.34 - rwrite(("DTEND", {"VALUE" : "DATE-TIME", "TZID" : tzid}, end or
2.35 - format_datetime(get_end_of_day(get_datetime(start, {"TZID" : tzid})))
2.36 - ))
2.37 + rwrite(("DTSTART", start_attr, start_value))
2.38 + rwrite(("DTEND", end_attr, end_value))
2.39 rwrite(("ORGANIZER", {}, self.user))
2.40
2.41 for participant in participants:
2.42 @@ -969,7 +973,7 @@
2.43 page.thead()
2.44 page.tr()
2.45 page.th(class_="dayheading", colspan=all_columns+1)
2.46 - page.add(self.format_date(day, "full"))
2.47 + self._day_heading(day)
2.48 page.th.close()
2.49 page.tr.close()
2.50 page.thead.close()
2.51 @@ -1092,21 +1096,37 @@
2.52
2.53 page.tr.close()
2.54
2.55 + def _day_heading(self, day):
2.56 + page = self.page
2.57 + value, identifier = self._day_value_and_identifier(day)
2.58 + slots = self.env.get_args().get("slot", [])
2.59 + self._slot_selector(value, identifier, slots)
2.60 + page.label(self.format_date(day, "full"), class_="day", for_=identifier)
2.61 +
2.62 def _time_point(self, point, endpoint):
2.63 page = self.page
2.64 value, identifier = self._slot_value_and_identifier(point, endpoint)
2.65 slots = self.env.get_args().get("slot", [])
2.66 + self._slot_selector(value, identifier, slots)
2.67 + page.label(self.format_time(point, "long"), class_="timepoint", for_=identifier)
2.68 +
2.69 + def _slot_selector(self, value, identifier, slots):
2.70 + page = self.page
2.71 if value in slots:
2.72 page.input(name="slot", type="checkbox", value=value, id=identifier, class_="newevent", checked="checked")
2.73 else:
2.74 page.input(name="slot", type="checkbox", value=value, id=identifier, class_="newevent")
2.75 - page.label(self.format_time(point, "long"), class_="timepoint", for_=identifier)
2.76
2.77 def _empty_slot(self, point, endpoint):
2.78 page = self.page
2.79 value, identifier = self._slot_value_and_identifier(point, endpoint)
2.80 page.label("Select/deselect period", class_="newevent popup", for_=identifier)
2.81
2.82 + def _day_value_and_identifier(self, day):
2.83 + value = "%s-" % format_datetime(day)
2.84 + identifier = "day-%s" % value
2.85 + return value, identifier
2.86 +
2.87 def _slot_value_and_identifier(self, point, endpoint):
2.88 value = "%s-%s" % (format_datetime(point), endpoint and format_datetime(endpoint) or "")
2.89 identifier = "slot-%s" % value
3.1 --- a/imiptools/dates.py Tue Feb 03 00:02:18 2015 +0100
3.2 +++ b/imiptools/dates.py Tue Feb 03 00:33:45 2015 +0100
3.3 @@ -70,6 +70,13 @@
3.4 else:
3.5 return dt.strftime("%Y%m%d")
3.6
3.7 +def get_datetime_item(dt):
3.8 + if not dt:
3.9 + return None, None
3.10 + value = format_datetime(dt)
3.11 + attr = isinstance(dt, datetime) and {"TZID" : dt.tzname(), "VALUE" : "DATE-TIME"} or {"VALUE" : "DATE"}
3.12 + return value, attr
3.13 +
3.14 def get_datetime(value, attr=None):
3.15
3.16 """
3.17 @@ -94,7 +101,9 @@
3.18
3.19 return to_timezone(dt, m.group("utc") and "UTC" or attr and attr.get("TZID") or None)
3.20
3.21 - if not attr or attr.get("VALUE") == "DATE":
3.22 + # Permit dates even if the VALUE is not set to DATE.
3.23 +
3.24 + if not attr or attr.get("VALUE") in (None, "DATE"):
3.25 m = match_date_icalendar(value)
3.26 if m:
3.27 year, month, day = map(m.group, ["year", "month", "day"])
3.28 @@ -108,6 +117,12 @@
3.29 def get_end_of_day(dt, tzid=None):
3.30 return get_start_of_day(dt + timedelta(1), tzid)
3.31
3.32 +def get_start_of_next_day(dt, tzid=None):
3.33 + if isinstance(dt, datetime):
3.34 + return get_end_of_day(dt, tzid)
3.35 + else:
3.36 + return dt + timedelta(1)
3.37 +
3.38 def ends_on_same_day(dt, end):
3.39 return (
3.40 dt.date() == end.date() or