# HG changeset patch # User Paul Boddie # Date 1268697498 -3600 # Node ID b8b10d95c10ed4a3e9876fd3c845f14f7aebaf4e # Parent b4356d0f6d078be83d0b3287d8a07871337c97cb Added support for "UTC" as time zone. Moved date and the new time constraint functionality to the Date and DateTime classes. Added initial support for specifying times in the new event action, changing the _get_input method to support purely optional integer fields. diff -r b4356d0f6d07 -r b8b10d95c10e EventAggregatorSupport.py --- a/EventAggregatorSupport.py Sun Mar 14 23:21:52 2010 +0100 +++ b/EventAggregatorSupport.py Tue Mar 16 00:58:18 2010 +0100 @@ -45,7 +45,7 @@ month_regexp_str = ur'(?P[0-9]{4})-(?P[0-9]{2})' date_regexp_str = ur'(?P[0-9]{4})-(?P[0-9]{2})-(?P[0-9]{2})' time_regexp_str = ur'(?P[0-2][0-9]):(?P[0-5][0-9])(?::(?P[0-6][0-9]))?' -timezone_offset_str = ur'(?:UTC)?(?P[-+])(?P[0-9]{2})(?::?(?P[0-9]{2}))?' +timezone_offset_str = ur'(UTC)?(?:(?P[-+])(?P[0-9]{2})(?::?(?P[0-9]{2}))?)?' timezone_regexp_str = ur'(?P' + timezone_offset_str + ')' datetime_regexp_str = date_regexp_str + ur'(?:\s+' + time_regexp_str + ur'(?:\s+' + timezone_regexp_str + ur')?)?' @@ -890,6 +890,15 @@ "A simple year-month-day representation." + def constrain(self): + year, month, day = self.as_tuple()[:3] + + month = max(min(month, 12), 1) + wd, last_day = calendar.monthrange(year, month) + day = max(min(day, last_day), 1) + + self.data[1:3] = month, day + def __str__(self): return "%04d-%02d-%02d" % self.as_tuple()[:3] @@ -943,8 +952,19 @@ "A simple date plus time representation." - def __init__(self, data): - Date.__init__(self, data) + def constrain(self): + Date.constrain(self) + + hour, minute, second = self.as_tuple()[3:6] + + if self.has_time(): + hour = max(min(hour, 23), 0) + minute = max(min(minute, 59), 0) + + if second is not None: + second = max(min(second, 60), 0) # support leap seconds + + self.data[3:6] = hour, minute, second def __str__(self): if self.has_time(): @@ -1034,6 +1054,11 @@ if not zone: return None + # Support explicit UTC zones. + + if zone == "UTC": + return 0, 0 + # Attempt to return a UTC offset where an explicit offset has been set. match = timezone_offset_regexp.match(zone) diff -r b4356d0f6d07 -r b8b10d95c10e actions/EventAggregatorNewEvent.py --- a/actions/EventAggregatorNewEvent.py Sun Mar 14 23:21:52 2010 +0100 +++ b/actions/EventAggregatorNewEvent.py Tue Mar 16 00:58:18 2010 +0100 @@ -14,8 +14,6 @@ from MoinMoin.Page import Page from MoinMoin.PageEditor import PageEditor import EventAggregatorSupport -import calendar -import re Dependencies = ['pages'] @@ -31,8 +29,12 @@ def _get_selected_for_list(self, value, input_values): return value in input_values and 'selected="selected"' or '' - def _get_input(self, form, name, default): - return int(form.get(name, [None])[0] or default) + def _get_input(self, form, name, default=None): + value = form.get(name, [None])[0] + if not value: # true if 0 obtained + return default + else: + return int(value) def get_form_html(self, buttons_html): _ = self._ @@ -77,6 +79,36 @@ del topics[i] break + # Initialise hour and minute lists. + + start_hour_list = [] + start_hour_list.append('') + start_minute_list = [] + start_minute_list.append('') + end_hour_list = [] + end_hour_list.append('') + end_minute_list = [] + end_minute_list.append('') + + start_hour = self._get_input(form, "start-hour") + end_hour = self._get_input(form, "end-hour") + start_minute = self._get_input(form, "start-minute") + end_minute = self._get_input(form, "end-minute") + + # Prepare hour and minute lists, selecting specified values. + + for hour in range(0, 24): + selected = self._get_selected(hour, start_hour) + start_hour_list.append('' % (hour, selected, hour)) + selected = self._get_selected(hour, end_hour) + end_hour_list.append('' % (hour, selected, hour)) + + for minute in range(0, 60): + selected = self._get_selected(minute, start_minute) + start_minute_list.append('' % (minute, selected, minute)) + selected = self._get_selected(minute, end_minute) + end_minute_list.append('' % (minute, selected, minute)) + # Initialise month lists. start_month_list = [] @@ -104,14 +136,27 @@ "buttons_html" : buttons_html, "category_label" : _("Categories"), "category_list" : "\n".join(category_list), + "start_month_list" : "\n".join(start_month_list), + "start_hour_list" : "\n".join(start_hour_list), + "start_minute_list" : "\n".join(start_minute_list), + "end_month_list" : "\n".join(end_month_list), + "end_hour_list" : "\n".join(end_hour_list), + "end_minute_list" : "\n".join(end_minute_list), + "start_label" : _("Start date (day, month, year)"), "start_day_default" : form.get("start-day", [""])[0], "start_year_default" : form.get("start-year", [""])[0] or EventAggregatorSupport.getCurrentYear(), + "start_time_label" : _("Start time (hour, minute, second)"), + "start_second_default" : form.get("start-second", [""])[0], + "end_label" : _("End date (day, month, year) - if different"), "end_day_default" : form.get("end-day", [""])[0], "end_year_default" : form.get("end-year", [""])[0], + "end_time_label" : _("End time (hour, minute, second)"), + "end_second_default" : form.get("end-second", [""])[0], + "title_label" : _("Event title/summary"), "title_default" : form.get("title", [""])[0], "description_label" : _("Event description"), @@ -120,13 +165,16 @@ "location_default" : form.get("location", [""])[0], "link_label" : _("Event URL"), "link_default" : form.get("link", [""])[0], + "topics_label" : _("Topics"), "add_topic_label" : _("Add topic"), "remove_topic_label" : _("Remove topic"), + "template_label" : _("Event template"), "template_default" : form.get("template", [""])[0] or template_default, "parent_label" : _("Parent page"), "parent_default" : form.get("parent", [""])[0], + "advanced_label" : _("Show advanced options"), "basic_label" : _("Show basic options"), } @@ -152,6 +200,18 @@ + + + + + + + + @@ -162,6 +222,18 @@ + + + + + + + + @@ -305,13 +377,19 @@ link = form.get("link", [None])[0] topics = form.get("topics", []) + start_zone = form.get("start-zone", [None])[0] + end_zone = form.get("end-zone", [None])[0] + # Validate certain fields. try: title = form["title"][0] template = form["template"][0] parent = form["parent"][0] + except (KeyError, IndexError): + return 0, _("Event title or template missing.") + try: start_day = self._get_input(form, "start-day", 0) start_month = self._get_input(form, "start-month", 0) start_year = self._get_input(form, "start-year", 0) @@ -319,25 +397,38 @@ end_month = self._get_input(form, "end-month", start_month) end_year = self._get_input(form, "end-year", start_year) - start_year, start_month, start_day = self.constrain_date(start_year, start_month, start_day) - end_year, end_month, end_day = self.constrain_date(end_year, end_month, end_day) - except (TypeError, ValueError): return 0, _("Days and years must be numbers yielding a valid date!") - except (KeyError, IndexError): - return 0, _("Event title or template missing.") + try: + start_hour = self._get_input(form, "start-hour") + start_minute = self._get_input(form, "start-minute") + start_second = self._get_input(form, "start-second") + + end_hour = self._get_input(form, "end-hour") + end_minute = self._get_input(form, "end-minute") + end_second = self._get_input(form, "end-second") - start_date = self.make_date_string(start_year, start_month, start_day) - end_date = self.make_date_string(end_year, end_month, end_day) + except (TypeError, ValueError): + return 0, _("Hours, minutes and seconds must be numbers yielding a valid time!") + + start_date = EventAggregatorSupport.DateTime( + (start_year, start_month, start_day, start_hour, start_minute, start_second, start_zone) + ) + start_date.constrain() + + end_date = EventAggregatorSupport.DateTime( + (end_year, end_month, end_day, end_hour, end_minute, end_second, end_zone) + ) + end_date.constrain() # An elementary date ordering check. - if start_date > end_date: + if (start_date.as_date() != end_date.as_date() or start_date.has_time() and end_date.has_time()) and start_date > end_date: start_date, end_date = end_date, start_date event_details = { - "start" : start_date, "end" : end_date, + "start" : str(start_date), "end" : str(end_date), "title" : title, "summary" : title, "description" : description, "location" : location, "link" : link, "topics" : [topic for topic in topics if topic] @@ -372,19 +463,6 @@ request.http_redirect(new_page.url(request, query)) return 1, None - def make_date_string(self, year, month, day): - return "%s-%s-%s" % ( - year and ("%04d" % year) or "YYYY", - month and ("%02d" % month) or "MM", - day and ("%02d" % day) or "DD" - ) - - def constrain_date(self, year, month, day): - if year and month and day: - wd, last_day = calendar.monthrange(year, month) - day = max(min(day, last_day), 1) - return year, month, day - # Action function. def execute(pagename, request):