示例#1
0
    def deserialize_dt(text):
        try:
            year, month, day = int(text[:4]), int(text[4:6]), int(text[6:8])
        except ValueError:
            raise exceptions.DeserializationError('malformed date-time: %r' % text)
        if u'T' in text:
            # time is also specified
            try:
                hour, minute, second = (
                    int(text[9:11]), int(text[11:13]), int(text[13:15]))
            except ValueError:
                raise exceptions.DeserializationError('malformed date-time: %r' % text)
        else:
            # only date is specified, use midnight
            hour, minute, second = (0, 0, 0)
        if u'Z' in text:
            # time is in utc
            tzinfo = pytz.utc
        else:
            # right now there is no support for VTIMEZONE/TZID since
            # this is a partial implementation of rfc2445 so we'll
            # just use the time zone specified in the Django settings.
            tzinfo = localtz

        dt = datetime.datetime(
            year, month, day, hour, minute, second, tzinfo=tzinfo)
        dt = dt.astimezone(localtz)

        # set tz to settings.TIME_ZONE and return offset-naive datetime
        return datetime.datetime(
            dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
示例#2
0
    def deserialize_dt(text):
        """
        Deserialize a rfc2445 text to a datetime.

        The setting RECURRENCE_USE_TZ determines if a naive or
        timezone aware datetime is returned.

        If this setting is not present the setting USE_TZ is used
        as a default.

        This setting is accessed via the `.settings.deserialize_tz`
        function.
        """
        try:
            year, month, day = int(text[:4]), int(text[4:6]), int(text[6:8])
        except ValueError:
            raise exceptions.DeserializationError('malformed date-time: %r' %
                                                  text)
        if u'T' in text:
            # time is also specified
            try:
                hour, minute, second = (int(text[9:11]), int(text[11:13]),
                                        int(text[13:15]))
            except ValueError:
                raise exceptions.DeserializationError(
                    'malformed date-time: %r' % text)
        else:
            # only date is specified, use midnight
            hour, minute, second = (0, 0, 0)
        if u'Z' in text:
            # time is in utc
            tzinfo = pytz.utc
        else:
            # right now there is no support for VTIMEZONE/TZID since
            # this is a partial implementation of rfc2445 so we'll
            # just use the time zone specified in the Django settings.
            tzinfo = localtz()

        dt = datetime.datetime(year,
                               month,
                               day,
                               hour,
                               minute,
                               second,
                               tzinfo=tzinfo)

        if settings.deserialize_tz():
            return dt

        dt = dt.astimezone(localtz())

        # set tz to settings.TIME_ZONE and return offset-naive datetime
        return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute,
                                 dt.second)
示例#3
0
def deserialize(text):
    """
    Deserialize a rfc2445 formatted string.

    This is a basic parser that is a partial implementation of rfc2445
    which pertains to specifying recurring date/times. Limitations
    include:

      - Only collects `DTSTART`, `DTEND`, `RRULE`, `EXRULE`, `RDATE`,
        and `EXDATE` properties.

      - Does not capture parameter options (i.e. RDATE;VALUE=PERIOD).
        `dateutil.rrule` does not support anything other than
        `DATE-TIME` parameter types.

      - `VTIMEZONE` and `TZID` can't be specified, so dates without
        the 'Z' marker will be localized to
        `settings.TIME_ZONE`. `datetime.datetime` objects in
        `Recurrence`/`Rrule` objects will be serialized as UTC.

      - The `DTSTART`, `DTEND`, `RDATE` and `EXDATE` properties also
        only support the `DATE-TIME` type.

    :Returns:
        A `Recurrence` instance.
    """
    def deserialize_dt(text):
        try:
            year, month, day = int(text[:4]), int(text[4:6]), int(text[6:8])
        except ValueError:
            raise exceptions.DeserializationError('malformed date-time: %r' %
                                                  text)
        if u'T' in text:
            # time is also specified
            try:
                hour, minute, second = (int(text[9:11]), int(text[11:13]),
                                        int(text[13:15]))
            except ValueError:
                raise exceptions.DeserializationError(
                    'malformed date-time: %r' % text)
        else:
            # only date is specified, use midnight
            hour, minute, second = (0, 0, 0)
        if u'Z' in text:
            # time is in utc
            tzinfo = pytz.utc
        else:
            # right now there is no support for VTIMEZONE/TZID since
            # this is a partial implementation of rfc2445 so we'll
            # just use the time zone specified in the Django settings.
            tzinfo = localtz

        dt = datetime.datetime(year,
                               month,
                               day,
                               hour,
                               minute,
                               second,
                               tzinfo=tzinfo)
        dt = dt.astimezone(localtz)

        # set tz to settings.TIME_ZONE and return offset-naive datetime
        return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute,
                                 dt.second)

    dtstart, dtend, rrules, exrules, rdates, exdates = None, None, [], [], [], []

    tokens = re.compile(u'(DTSTART|DTEND|RRULE|EXRULE|RDATE|EXDATE)[^:]*:(.*)',
                        re.MULTILINE).findall(text)

    if not tokens and text:
        raise exceptions.DeserializationError('malformed data')

    for label, param_text in tokens:
        if not param_text:
            raise exceptions.DeserializationError('empty property: %r' % label)
        if u'=' not in param_text:
            params = param_text
        else:
            params = {}
            param_tokens = filter(lambda p: p, param_text.split(u';'))
            for item in param_tokens:
                try:
                    param_name, param_value = map(lambda i: i.strip(),
                                                  item.split(u'=', 1))
                except ValueError:
                    raise exceptions.DeserializationError(
                        'missing parameter value: %r' % item)
                params[param_name] = map(lambda i: i.strip(),
                                         param_value.split(u','))

        if label in (u'RRULE', u'EXRULE'):
            kwargs = {}
            for key, value in params.items():
                if key == u'FREQ':
                    try:
                        kwargs[str(key.lower())] = list(
                            Rule.frequencies).index(value[0])
                    except ValueError:
                        raise exceptions.DeserializationError(
                            'bad frequency value: %r' % value[0])
                elif key == u'INTERVAL':
                    try:
                        kwargs[str(key.lower())] = int(value[0])
                    except ValueError:
                        raise exceptions.DeserializationError(
                            'bad interval value: %r' % value[0])
                elif key == u'WKST':
                    try:
                        kwargs[str(key.lower())] = to_weekday(value[0])
                    except ValueError:
                        raise exceptions.DeserializationError(
                            'bad weekday value: %r' % value[0])
                elif key == u'COUNT':
                    try:
                        kwargs[str(key.lower())] = int(value[0])
                    except ValueError:
                        raise exceptions.DeserializationError(
                            'bad count value: %r' % value[0])
                elif key == u'UNTIL':
                    kwargs[str(key.lower())] = deserialize_dt(value[0])
                elif key == u'BYDAY':
                    bydays = []
                    for v in value:
                        try:
                            bydays.append(to_weekday(v))
                        except ValueError:
                            raise exceptions.DeserializationError(
                                'bad weekday value: %r' % v)
                    kwargs[str(key.lower())] = bydays
                elif key.lower() in Rule.byparams:
                    numbers = []
                    for v in value:
                        try:
                            numbers.append(int(v))
                        except ValueError:
                            raise exceptions.DeserializationError(
                                'bad value: %r' % value)
                    kwargs[str(key.lower())] = numbers
                else:
                    raise exceptions.DeserializationError('bad parameter: %r' %
                                                          key)
            if 'freq' not in kwargs:
                raise exceptions.DeserializationError(
                    'frequency parameter missing from rule')
            if label == u'RRULE':
                rrules.append(Rule(**kwargs))
            else:
                exrules.append(Rule(**kwargs))
        elif label == u'DTSTART':
            dtstart = deserialize_dt(params)
        elif label == u'DTEND':
            dtend = deserialize_dt(params)
        elif label == u'RDATE':
            rdates.append(deserialize_dt(params))
        elif label == u'EXDATE':
            exdates.append(deserialize_dt(params))

    return Recurrence(dtstart, dtend, rrules, exrules, rdates, exdates)