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)
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])