def to_ical(self): sign = "" if self.td.days < 0: sign = "-" self.td = -self.td timepart = "" if self.td.seconds: timepart = "T" hours = self.td.seconds // 3600 minutes = self.td.seconds % 3600 // 60 seconds = self.td.seconds % 60 if hours: timepart += "%dH" % hours if minutes or (hours and seconds): timepart += "%dM" % minutes if seconds: timepart += "%dS" % seconds if self.td.days == 0 and timepart: return (compat.unicode_type(sign).encode('utf-8') + b'P' + compat.unicode_type(timepart).encode('utf-8')) else: return (compat.unicode_type(sign).encode('utf-8') + b'P' + compat.unicode_type(abs(self.td.days)).encode('utf-8') + b'D' + compat.unicode_type(timepart).encode('utf-8'))
def to_ical(self): return compat.unicode_type(self).encode('utf-8')
def from_ical(cls, st, multiple=False): """Populates the component recursively from a string. """ stack = [] # a stack of components comps = [] for line in Contentlines.from_ical(st): # raw parsing if not line: continue try: name, params, vals = line.parts() except ValueError as e: # if unable to parse a line within a component # that ignores exceptions, mark the component # as broken and skip the line. otherwise raise. component = stack[-1] if stack else None if not component or not component.ignore_exceptions: raise component.errors.append((None, unicode_type(e))) continue uname = name.upper() # check for start of component if uname == 'BEGIN': # try and create one of the components defined in the spec, # otherwise get a general Components for robustness. c_name = vals.upper() c_class = component_factory.get(c_name, Component) # If component factory cannot resolve ``c_name``, the generic # ``Component`` class is used which does not have the name set. # That's opposed to the usage of ``cls``, which represents a # more concrete subclass with a name set (e.g. VCALENDAR). component = c_class() if not getattr(component, 'name', ''): # undefined components component.name = c_name stack.append(component) # check for end of event elif uname == 'END': # we are done adding properties to this component # so pop it from the stack and add it to the new top. component = stack.pop() if not stack: # we are at the end comps.append(component) else: stack[-1].add_component(component) if vals == 'VTIMEZONE' and \ 'TZID' in component and \ component['TZID'] not in pytz.all_timezones and \ component['TZID'] not in _timezone_cache: _timezone_cache[component['TZID']] = component.to_tz() # we are adding properties to the current top of the stack else: factory = types_factory.for_property(name) component = stack[-1] if stack else None if not component: raise ValueError('Property "{prop}" does not have ' 'a parent component.'.format(prop=name)) datetime_names = ('DTSTART', 'DTEND', 'RECURRENCE-ID', 'DUE', 'FREEBUSY', 'RDATE', 'EXDATE') try: if name in datetime_names and 'TZID' in params: vals = factory(factory.from_ical(vals, params['TZID'])) else: vals = factory(factory.from_ical(vals)) except ValueError as e: if not component.ignore_exceptions: raise component.errors.append((uname, unicode_type(e))) component.add(name, None, encode=0) else: vals.params = params component.add(name, vals, encode=0) if multiple: return comps if len(comps) > 1: raise ValueError('Found multiple components where ' 'only one is allowed: {st!r}'.format(**locals())) if len(comps) < 1: raise ValueError('Found no components where ' 'exactly one is required: ' '{st!r}'.format(**locals())) return comps[0]