imip-agent

imiptools/dates.py

157:eff00f10d12a
2015-01-22 Paul Boddie Handle "naive" datetimes in to_utc_datetime.
     1 #!/usr/bin/env python     2      3 """     4 Date processing functions.     5      6 Copyright (C) 2014, 2015 Paul Boddie <paul@boddie.org.uk>     7      8 This program is free software; you can redistribute it and/or modify it under     9 the terms of the GNU General Public License as published by the Free Software    10 Foundation; either version 3 of the License, or (at your option) any later    11 version.    12     13 This program is distributed in the hope that it will be useful, but WITHOUT    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    16 details.    17     18 You should have received a copy of the GNU General Public License along with    19 this program.  If not, see <http://www.gnu.org/licenses/>.    20 """    21     22 from datetime import date, datetime    23 from pytz import timezone, UnknownTimeZoneError    24 import re    25     26 # iCalendar date and datetime parsing (from DateSupport in MoinSupport).    27     28 date_icalendar_regexp_str = ur'(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})'    29 datetime_icalendar_regexp_str = date_icalendar_regexp_str + \    30     ur'(?:' \    31     ur'T(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-6][0-9])' \    32     ur'(?P<utc>Z)?' \    33     ur')?'    34     35 match_date_icalendar = re.compile(date_icalendar_regexp_str, re.UNICODE).match    36 match_datetime_icalendar = re.compile(datetime_icalendar_regexp_str, re.UNICODE).match    37     38 def to_utc_datetime(dt):    39     if not dt:    40         return None    41     elif isinstance(dt, datetime):    42         return to_timezone(dt, "UTC")    43     else:    44         return dt    45     46 def to_timezone(dt, name):    47     try:    48         tz = name and timezone(name) or None    49     except UnknownTimeZoneError:    50         tz = None    51     return to_tz(dt, tz)    52     53 def to_tz(dt, tz):    54     if tz is not None:    55         if not dt.tzinfo:    56             return tz.localize(dt)    57         else:    58             return dt.astimezone(tz)    59     else:    60         return dt    61     62 def format_datetime(dt):    63     if not dt:    64         return None    65     elif isinstance(dt, datetime):    66         if dt.tzname() == "UTC":    67             return dt.strftime("%Y%m%dT%H%M%SZ")    68         else:    69             return dt.strftime("%Y%m%dT%H%M%S")    70     else:    71         return dt.strftime("%Y%m%d")    72     73 def get_datetime(value, attr=None):    74     75     """    76     Return a datetime object from the given 'value' in iCalendar format, using    77     the 'attr' mapping (if specified) to control the conversion.    78     """    79     80     if not attr or attr.get("VALUE") in (None, "DATE-TIME"):    81         m = match_datetime_icalendar(value)    82         if m:    83             dt = datetime(    84                 int(m.group("year")), int(m.group("month")), int(m.group("day")),    85                 int(m.group("hour")), int(m.group("minute")), int(m.group("second"))    86                 )    87     88             # Impose the indicated timezone.    89             # NOTE: This needs an ambiguity policy for DST changes.    90     91             return to_timezone(dt, m.group("utc") and "UTC" or attr and attr.get("TZID") or None)    92     93     if not attr or attr.get("VALUE") == "DATE":    94         m = match_date_icalendar(value)    95         if m:    96             return date(    97                 int(m.group("year")), int(m.group("month")), int(m.group("day"))    98                 )    99     return None   100    101 def get_start_of_day(dt):   102     return datetime(dt.year, dt.month, dt.day, 0, 0, tzinfo=dt.tzinfo)   103    104 # vim: tabstop=4 expandtab shiftwidth=4