def ExceptionDateTimeFromAirsync(ctx): parser_ctx, transform_ctx = xml2util.ExtractContexts(ctx) src_node = transform_ctx.current() dst_node = transform_ctx.insertNode() exception_deleted = xml2util.GetNodeValue( xml2util.FindChildNode(src_node, "Deleted")) exception_date = xml2util.GetNodeValue( xml2util.FindChildNode(src_node, "ExceptionStartTime")) if exception_deleted != "1": raise ValueError( "Opensync does not support exceptions for modified occurrences") # We need to convert to current timezone if one is provided, else # we can assume UTC date = dateutil.TextToDate(exception_date) curtz = tzdatabase.tzdb.GetCurrentTimezone() if curtz != None: date = date.astimezone(curtz) dst_node.setProp("TimezoneID", curtz.name) dst_node = transform_ctx.insertNode() dst_node.setProp("Value", "DATE") tznode = dst_node.newChild(None, "Content", date.strftime(DATE_FORMAT_SHORT)) return ""
def NewTZComponentFromXML(node, tzdb): tzid = xml2util.GetNodeAttr(node, "TimezoneID") comp = xml2util.GetNodeAttr(node, "TZComponent") if tzid and comp: tz = tzdb.GetTimezone(tzid) if tz != None: component = tzutils.tzone.TZComponent() child = node.children while child != None: content = str(child.content).strip() if child.name == "TZName": component.name = child.content if child.name == "DateTimeStart": component.startdate = dateutil.TextToDate(content) if child.name == "TZOffsetFrom": component.offsetfrom = dateutil.OffsetToDelta(content) if child.name == "TZOffsetTo": component.offset = dateutil.OffsetToDelta(content) if child.name == "RecurrenceDateTime": component.rdates.append( dateutil.XMLDateTimeToDate(child, tzdb)) # we don't care about 'Comment' child = child.next if comp == "Standard": tz.stdcomponents.append(component) elif comp == "Daylight": tz.dstcomponents.append(component) else: print "Unknown TZ component type %s" % comp.content return True else: print "No timezone available for component %s" % tzid return False else: return False
def OSDateFromAirsync(ctx): parser_ctx, transform_ctx = xml2util.ExtractContexts(ctx) tznode = transform_ctx.current() date = dateutil.TextToDate(xml2util.GetNodeValue(transform_ctx.current())) date.replace(tzinfo=tzutils.tzone.utc) # We are going from AirSync, so 'date' will be in UTC # If we have a current timezone, set it. dst_node = transform_ctx.insertNode() dst_node.setProp("Value","DATE-TIME") curtz = tzdatabase.tzdb.GetCurrentTimezone() if curtz!=None: date = date.astimezone(curtz) dst_node.setProp("TimezoneID",curtz.name) tznode=dst_node.newChild(None,"Content",date.strftime(DATE_FORMAT_EVENT)) return ""
def AppendStringRule(self, rule): cmd, val = rule.split("=") if cmd == "FREQ": self.freq = YEARLY if val in FREQS.keys(): self.freq = FREQS[val] return True return False if cmd == "INTERVAL": self.interval = int(val) return True if cmd == "COUNT": self.count = int(val) return True if cmd == "UNTIL": self.until = dateutil.TextToDate(val) return True if cmd == "BYMONTH": self.byMonth += list(int(x) for x in val.split(',')) self.byMonth.sort() return True if cmd == "BYWEEKNO": self.byWeekNo += list(int(x) for x in val.split(',')) self.byWeekNo.sort() return True if cmd == "BYDAY": self.byDay = [] l = list(val.split(',')) for x in l: if len(x) >= 2: day = x.lstrip("-+1234567890") if WEEKDAYS.has_key(day): d = WEEKDAYS[day] pos = 0 if len(x) > 2: pos = (int(x[0:len(x) - 2])) self.byDay.append((d, pos)) else: return False self.byDay.sort() return True if cmd == "BYMONTHDAY": self.byMonthDay += list(int(x) for x in val.split(',')) self.byMonthDay.sort() return True if cmd == "BYYEARDAY": self.byYearDay += list(int(x) for x in val.split(',')) self.byYearDay.sort() return True if cmd == "BYHOUR": self.byHour += list(int(x) for x in val.split(',')) self.byHour.sort() return True if cmd == "BYMINUTE": self.byMinute += list(int(x) for x in val.split(',')) self.byMinute.sort() return True if cmd == "BYSECOND": self.bySecond += list(int(x) for x in val.split(',')) self.bySecond.sort() return True return False
def SetStartDateFromText(self, date): self.startdate = dateutil.TextToDate(date)
def RecurrenceRuleToAirsync(ctx): parser_ctx, transform_ctx = xml2util.ExtractContexts(ctx) src_node = transform_ctx.current() dst_node = transform_ctx.insertNode() # Extract the rules src_rules = {} child = src_node.children while child != None: src_rules[child.name.lower()] = xml2util.GetNodeValue(child) child = child.next # Interval, Count, and Until rules have straightforward conversions if src_rules.has_key("interval"): dst_node.newChild(None, "Interval", src_rules["interval"]) if src_rules.has_key("until"): dst_node.newChild(None, "Until", dateutil.TextToDate(src_rules["until"]).strftime(DATE_FORMAT_EVENT)) if src_rules.has_key("count"): dst_node.newChild(None, "Occurrences", src_rules["count"]) # Handle different types of recurrences on a case-by-case basis if src_rules["frequency"].lower() == "daily": # There really isn't much to convert in this case.. dst_node.newChild(None, "Type", "0") elif src_rules["frequency"].lower() == "weekly": dst_node.newChild(None, "Type", "1") dst_node.newChild(None, "DayOfWeek", str(VcalDaysToAirsyncDays(src_rules["byday"]))) elif src_rules["frequency"].lower() == "monthly": if src_rules.has_key("bymonthday"): dst_node.newChild(None, "Type", "2") dst_node.newChild(None, "DayOfMonth", src_rules["bymonthday"]) elif src_rules.has_key("byday"): week, day = VcalSplitByDay(src_rules["byday"]) dst_node.newChild(None, "Type", "3") dst_node.newChild(None, "DayOfWeek", str(VcalDaysToAirsyncDays(day))) if week >= 0: dst_node.newChild(None, "WeekOfMonth", week) elif week == -1: # Airsync deals with this as a special case dst_node.newChild(None, "WeekOfMonth", "5") else: # Not supported (as far as I can tell...) # Airsync cannot count backwards from the end of the # month in general raise ValueError("Airsync does not support counting from end of month") else: # It seems like this should be against the rules, and filling in # a default might not make sense because either of the above interpretations # is equally valid. raise ValueError("Monthly events must either specify BYMONTHDAY or BYDAY rules") elif src_rules["frequency"].lower() == "yearly": if src_rules.has_key("bymonth"): if src_rules.has_key("bymonthday"): dst_node.newChild(None, "Type", "5") dst_node.newChild(None, "MonthOfYear", src_rules["bymonth"]) dst_node.newChild(None, "DayOfMonth", src_rules["bymonthday"]) elif src_rules.has_key("byday"): week, day = VcalSplitByDay(src_rules["byday"]) dst_node.newChild(None, "Type", "6") dst_node.newChild(None, "MonthOfYear", src_rules["bymonth"]) dst_node.newChild(None, "DayOfWeek", str(VcalDaysToAirsyncDays(day))) if week >= 0: dst_node.newChild(None, "WeekOfMonth", week) elif week == -1: # Airsync deals with this as a special case dst_node.newChild(None, "WeekOfMonth", "5") else: # Not supported (as far as I can tell...) # Airsync cannot count backwards from the end of the # month in general raise ValueError("Airsync does not support counting from end of month") else: # It seems like this should be against the rules, and filling in # a default might not make sense because either of the above interpretations # is equally valid. raise ValueError("Yearly events which are by month must either specify BYMONTHDAY or BYDAY rules") elif src_rules.has_key("byyearday"): # Not supported (as far as I can tell...) # Airsync does not have a 'DayOfYear' field raise ValueError("Airsync does not support day-of-year yearly events") else: # we need to get the start/recurrence date from the start date # Get the start date - we need this to expand yearly rules # We should always have a start date in a legal event! start = xml2util.FindChildNode(src_node.parent,"DateStarted") date = dateutil.XMLDateTimeToDate(start,tzdatabase.tzdb) utcdate = date.astimezone(tzutils.tzone.utc) # We need the month and the day dst_node.newChild(None,"Type", "5") dst_node.newChild(None,"MonthOfYear",str(utcdate.month)) dst_node.newChild(None,"DayOfMonth",str(utcdate.day)) # 'Count' is already handled return ""