예제 #1
0
def serialize(rule_or_recurrence):
    """
    Serialize a `Rule` or `Recurrence` instance.

    `Rule` instances are wrapped as an rrule in a `Recurrence`
    instance before serialization, and will serialize as the `RRULE`
    property.

    All `datetime.datetime` objects will be converted and serialized
    as UTC.

    :Returns:
        A rfc2445 formatted unicode string.
    """
    def serialize_dt(dt):
        if not dt.tzinfo:
            dt = localtz().localize(dt)
        dt = dt.astimezone(pytz.utc)

        return u'%s%s%sT%s%s%sZ' % (
            str(dt.year).rjust(4, '0'),
            str(dt.month).rjust(2, '0'),
            str(dt.day).rjust(2, '0'),
            str(dt.hour).rjust(2, '0'),
            str(dt.minute).rjust(2, '0'),
            str(dt.second).rjust(2, '0'),
        )

    def serialize_rule(rule):
        values = []
        values.append((u'FREQ', [Rule.frequencies[rule.freq]]))

        if rule.interval != 1:
            values.append((u'INTERVAL', [str(int(rule.interval))]))
        if rule.wkst:
            values.append(
                (u'WKST',
                 [Rule.weekdays[getattr(rule.wkst, 'number', rule.wkst)]]))

        if rule.count is not None:
            values.append((u'COUNT', [str(rule.count)]))
        elif rule.until is not None:
            values.append((u'UNTIL', [serialize_dt(rule.until)]))

        if rule.byday:
            days = []
            for d in rule.byday:
                d = to_weekday(d)
                # TODO - this if/else copies what Weekday's __repr__
                # does - perhaps we should refactor it into a __str__
                # method on Weekday?
                if d.index:
                    days.append(u'%s%s' % (d.index, Rule.weekdays[d.number]))
                else:
                    days.append(Rule.weekdays[d.number])
            values.append((u'BYDAY', days))

        remaining_params = list(Rule.byparams)
        remaining_params.remove('byday')
        for param in remaining_params:
            value_list = getattr(rule, param, None)
            if value_list:
                values.append((param.upper(), [str(n) for n in value_list]))

        return u';'.join(u'%s=%s' % (i[0], u','.join(i[1])) for i in values)

    if rule_or_recurrence is None:
        return None

    try:
        validate(rule_or_recurrence)
    except exceptions.ValidationError as error:
        raise exceptions.SerializationError(error.args[0])

    obj = rule_or_recurrence
    if isinstance(obj, Rule):
        obj = Recurrence(rrules=[obj])

    items = []

    if obj.dtstart:
        if obj.dtstart.tzinfo:
            dtstart = serialize_dt(obj.dtstart.astimezone(pytz.utc))
        else:
            dtstart = serialize_dt(localtz().localize(obj.dtstart).astimezone(
                pytz.utc))
        items.append((u'DTSTART', dtstart))
    if obj.dtend:
        if obj.dtend.tzinfo:
            dtend = serialize_dt(obj.dtend.astimezone(pytz.utc))
        else:
            dtend = serialize_dt(localtz().localize(obj.dtend).astimezone(
                pytz.utc))
        items.append((u'DTEND', dtend))

    for rrule in obj.rrules:
        items.append((u'RRULE', serialize_rule(rrule)))
    for exrule in obj.exrules:
        items.append((u'EXRULE', serialize_rule(exrule)))

    for rdate in obj.rdates:
        if rdate.tzinfo:
            rdate = rdate.astimezone(pytz.utc)
        else:
            rdate = localtz().localize(rdate).astimezone(pytz.utc)
        items.append((u'RDATE', serialize_dt(rdate)))
    for exdate in obj.exdates:
        if exdate.tzinfo:
            exdate = exdate.astimezone(pytz.utc)
        else:
            exdate = localtz().localize(exdate).astimezone(pytz.utc)
        items.append((u'EXDATE', serialize_dt(exdate)))

    return u'\n'.join(u'%s:%s' % i for i in items)
예제 #2
0
def serialize(rule_or_recurrence):
    """
    Serialize a `Rule` or `Recurrence` instance.

    `Rule` instances are wrapped as an rrule in a `Recurrence`
    instance before serialization, and will serialize as the `RRULE`
    property.

    All `datetime.datetime` objects will be converted and serialized
    as UTC.

    :Returns:
        A rfc2445 formatted unicode string.
    """
    def serialize_dt(dt):
        if not dt.tzinfo:
            dt = localtz.localize(dt)
        dt = dt.astimezone(pytz.utc)

        return u'%s%s%sT%s%s%sZ' % (
            str(dt.year).rjust(4, '0'),
            str(dt.month).rjust(2, '0'),
            str(dt.day).rjust(2, '0'),
            str(dt.hour).rjust(2, '0'),
            str(dt.minute).rjust(2, '0'),
            str(dt.second).rjust(2, '0'),
        )

    def serialize_rule(rule):
        values = []
        values.append((u'FREQ', [Rule.frequencies[rule.freq]]))

        if rule.interval != 1:
            values.append((u'INTERVAL', [str(int(rule.interval))]))
        if rule.wkst:
            values.append((u'WKST', [Rule.weekdays[rule.wkst]]))
        if rule.count is not None:
            values.append((u'COUNT', [str(rule.count)]))
        elif rule.until is not None:
            values.append((u'UNTIL', [serialize_dt(rule.until)]))

        if rule.byday:
            days = []
            for d in rule.byday:
                d = to_weekday(d)
                if d.index:
                    days.append(u'%s%s' % (d.index, Rule.weekdays[d.number]))
                else:
                    days.append(Rule.weekdays[d.number])
            values.append((u'BYDAY', days))

        remaining_params = list(Rule.byparams)
        remaining_params.remove('byday')
        for param in remaining_params:
            value_list = getattr(rule, param, None)
            if value_list:
                values.append((param.upper(), [str(n) for n in value_list]))

        return u';'.join(u'%s=%s' % (i[0], u','.join(i[1])) for i in values)

    if rule_or_recurrence is None:
        return None

    try:
        validate(rule_or_recurrence)
    except exceptions.ValidationError, error:
        raise exceptions.SerializationError(error.args[0])