def parse(self, ins): result = super(Calendar, self).parse(ins) # We need to store all timezones in the static object so they can be accessed by any date object from pycalendar.timezonedb import TimezoneDatabase TimezoneDatabase.mergeTimezones(self, self.getComponents(definitions.cICalComponent_VTIMEZONE)) return result
def timeZoneSecondsOffset(self, dt, relative_to_utc=False): if self.mUTC: return 0 elif self.mTimezone is None: return TimezoneDatabase.getTimezoneOffsetSeconds(Timezone.sDefaultTimezone.getTimezoneID(), dt, relative_to_utc) elif isinstance(self.mTimezone, int): return self.mTimezone else: # Look up timezone and resolve date using default timezones return TimezoneDatabase.getTimezoneOffsetSeconds(self.mTimezone, dt, relative_to_utc)
def setUp(self): super(TestTimezoneDB, self).setUp() # Standard components explicitly added for vtz in StandardTZs: cal = Calendar() TimezoneDatabase.getTimezoneDatabase()._addStandardTimezone(cal.parseComponent(StringIO(vtz))) # Just parsing will add as non-standard for vtz in NonStandardTZs: Calendar.parseData(vtz)
def timeZoneSecondsOffset(self, dt, relative_to_utc=False): if self.mUTC: return 0 elif self.mTimezone is None: return TimezoneDatabase.getTimezoneOffsetSeconds( Timezone.sDefaultTimezone.getTimezoneID(), dt, relative_to_utc) elif isinstance(self.mTimezone, int): return self.mTimezone else: # Look up timezone and resolve date using default timezones return TimezoneDatabase.getTimezoneOffsetSeconds( self.mTimezone, dt, relative_to_utc)
def timeZoneDescriptor(self, dt): if self.mUTC: return "(UTC)" elif self.mTimezone is None: return TimezoneDatabase.getTimezoneDescriptor(Timezone.sDefaultTimezone.getTimezoneID(), dt) elif isinstance(self.mTimezone, int): sign = "-" if self.mTimezone < 0 else "+" hours = abs(self.mTimezone) / 3600 minutes = divmod(abs(self.mTimezone) / 60, 60)[1] return "%s%02d%02d" % (sign, hours, minutes,) else: # Look up timezone and resolve date using default timezones return TimezoneDatabase.getTimezoneDescriptor(self.mTimezone, dt)
def create(empty=False): """ Create a timezone database from the files pointed to by the config. The empty option is used only for testing and will point the DB at an empty directory - i.e., no standard timezones are used. @param empty: set to C{True} when doing certain tests that do not want the standard timezone database used. @type empty: C{bool} """ if empty: TimezoneCache.dirName = "" else: TimezoneCache.dirName = None TimezoneCache.validatePath() TimezoneCache.version = TimezoneCache.getTZVersion(TimezoneCache.getDBPath()) TimezoneDatabase.createTimezoneDatabase(TimezoneCache.getDBPath())
def setUp(self): super(TestTimezoneDBCache, self).setUp() # Use temp dbpath tmpdir = tempfile.mkdtemp() TimezoneDatabase.createTimezoneDatabase(tmpdir) # Save standard components to temp directory for vtz in StandardTZs: cal = Calendar() tz = cal.parseComponent(StringIO(vtz)) tzid_parts = tz.getID().split("/") if not os.path.exists(os.path.join(tmpdir, tzid_parts[0])): os.makedirs(os.path.join(tmpdir, tzid_parts[0])) with open(os.path.join(tmpdir, "{}.ics".format(tz.getID())), "w") as f: f.write(vtz)
def stripStandardTimezones(self): """ Remove VTIMEZONE components from this L{Calendar} if the corresponding TZIDs are in the timezone database. @return: L{True} if changes were made, L{False} otherwise @rtype: L{bool} """ from pycalendar.timezonedb import TimezoneDatabase changed = False for component in self.getComponents(definitions.cICalComponent_VTIMEZONE): tz = TimezoneDatabase.getTimezone(component.getID()) if tz is not None and TimezoneDatabase.isStandardTimezone(component.getID()): self.removeComponent(component) changed = True return changed
def timeZoneDescriptor(self, dt): if self.mUTC: return "(UTC)" elif self.mTimezone is None: return TimezoneDatabase.getTimezoneDescriptor( Timezone.sDefaultTimezone.getTimezoneID(), dt) elif isinstance(self.mTimezone, int): sign = "-" if self.mTimezone < 0 else "+" hours = abs(self.mTimezone) / 3600 minutes = divmod(abs(self.mTimezone) / 60, 60)[1] return "%s%02d%02d" % ( sign, hours, minutes, ) else: # Look up timezone and resolve date using default timezones return TimezoneDatabase.getTimezoneDescriptor(self.mTimezone, dt)
def includeMissingTimezones(self, includeTimezones=None): """ For each timezone referenced in this L{Calendar}, if the corresponding VTIMEZONE component is not present, then add the matching component from the timezone database. L{includeTimezones} indicates what set of timezones should be automatically included. If set to L{None} the default is L{Calendar.NO_TIMEZONES}. Otherwise, one of L{Calendar.ALL_TIMEZONES}, L{Calendar.NONSTD_TIMEZONES}, or L{Calendar.NO_TIMEZONES} must be used. @param includeTimezones: indicated whether all, only non-standard or no timezones are included @type includeTimezones: L{int} or L{None} """ # Don't add anything in this case if includeTimezones == Calendar.NO_TIMEZONES: return if includeTimezones is None: includeTimezones = Calendar.NONSTD_TIMEZONES # Get timezone names from each component tzids = set() for component in self.mComponents: if component.getType() != definitions.cICalComponent_VTIMEZONE: component.getTimezones(tzids) # Make sure each timezone is in current calendar from pycalendar.timezonedb import TimezoneDatabase for tzid in tzids: # Skip standard timezones if requested if includeTimezones == Calendar.NONSTD_TIMEZONES and TimezoneDatabase.isStandardTimezone( tzid): continue tz = self.getTimezone(tzid) if tz is None: # Find it in the static object tz = TimezoneDatabase.getTimezone(tzid) if tz is not None: dup = tz.duplicate() self.addComponent(dup)
def test_isStandardTimezone(self): """ L{TimezoneDatabase.isStandardTimezone} returns correct result. """ data = ( ("America/New_York", True), ("America/Los_Angeles", True), ("America/Cupertino", False), ("America/FooBar", False), ) for tzid, result in data: self.assertEqual(TimezoneDatabase.isStandardTimezone(tzid), result, "Failed {}".format(tzid))
def readVTZ(tzid): """ Try to load the specified TZID as a calendar object from the database. Raise if not found. """ if tzid not in cachedVTZs: tzcal = TimezoneDatabase.getTimezoneInCalendar(tzid) if tzcal: cachedVTZs[tzid] = tzcal else: raise TimezoneException("Unknown time zone: %s" % (tzid, )) return cachedVTZs[tzid]
def readVTZ(tzid): """ Try to load the specified TZID as a calendar object from the database. Raise if not found. """ if tzid not in cachedVTZs: tzcal = TimezoneDatabase.getTimezoneInCalendar(tzid) if tzcal: cachedVTZs[tzid] = tzcal else: raise TimezoneException("Unknown time zone: %s" % (tzid,)) return cachedVTZs[tzid]
def includeMissingTimezones(self, includeTimezones=None): """ For each timezone referenced in this L{Calendar}, if the corresponding VTIMEZONE component is not present, then add the matching component from the timezone database. L{includeTimezones} indicates what set of timezones should be automatically included. If set to L{None} the default is L{Calendar.NO_TIMEZONES}. Otherwise, one of L{Calendar.ALL_TIMEZONES}, L{Calendar.NONSTD_TIMEZONES}, or L{Calendar.NO_TIMEZONES} must be used. @param includeTimezones: indicated whether all, only non-standard or no timezones are included @type includeTimezones: L{int} or L{None} """ # Don't add anything in this case if includeTimezones == Calendar.NO_TIMEZONES: return if includeTimezones is None: includeTimezones = Calendar.NONSTD_TIMEZONES # Get timezone names from each component tzids = set() for component in self.mComponents: if component.getType() != definitions.cICalComponent_VTIMEZONE: component.getTimezones(tzids) # Make sure each timezone is in current calendar from pycalendar.timezonedb import TimezoneDatabase for tzid in tzids: # Skip standard timezones if requested if includeTimezones == Calendar.NONSTD_TIMEZONES and TimezoneDatabase.isStandardTimezone(tzid): continue tz = self.getTimezone(tzid) if tz is None: # Find it in the static object tz = TimezoneDatabase.getTimezone(tzid) if tz is not None: dup = tz.duplicate() self.addComponent(dup)
def test_getTimezoneInCalendar(self): """ L{TimezoneDatabase.getTimezoneInCalendar} returns correct result. """ data = ( ("America/New_York", True), ("America/Los_Angeles", True), ("America/Cupertino", True), ("America/FooBar", False), ) for tzid, result in data: cal = TimezoneDatabase.getTimezoneInCalendar(tzid) if result: self.assertTrue(cal is not None) self.assertEqual(cal.getComponents()[0].getID(), tzid) else: self.assertTrue(cal is None)
def test_getTimezone(self): """ L{TimezoneDatabase.getTimezone} returns correct result. """ data = ( ("America/New_York", True), ("America/Los_Angeles", True), ("America/Cupertino", True), ("America/FooBar", False), ) for tzid, result in data: tz = TimezoneDatabase.getTimezone(tzid) if result: self.assertTrue(tz is not None) self.assertEqual(tz.getID(), tzid) else: self.assertTrue(tz is None)
def clear(): TimezoneDatabase.clearTimezoneDatabase()
def tearDown(self): TimezoneDatabase.clearTimezoneDatabase()
def parseComponent(self, ins): result = None LOOK_FOR_VCALENDAR = 0 GET_PROPERTY_OR_COMPONENT = 1 GOT_VCALENDAR = 4 state = LOOK_FOR_VCALENDAR # Get lines looking for start of calendar lines = [None, None] comp = self compend = None componentstack = [] got_timezone = False while readFoldedLine(ins, lines): line = lines[0] if state == LOOK_FOR_VCALENDAR: # Look for start if line == self.getBeginDelimiter(): # Next state state = GET_PROPERTY_OR_COMPONENT # Handle blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("iCalendar data has blank lines") # Unrecognized data else: raise InvalidData("iCalendar data not recognized", line) elif state == GET_PROPERTY_OR_COMPONENT: # Parse property or look for start of component if line.startswith("BEGIN:"): # Push previous details to stack componentstack.append((comp, compend,)) # Start a new component comp = self.sComponentType.makeComponent(line[6:], comp) compend = comp.getEndDelimiter() # Cache as result - but only the first one, we ignore the rest if result is None: result = comp # Look for timezone component to trigger timezone merge only if one is present if comp.getType() == definitions.cICalComponent_VTIMEZONE: got_timezone = True elif line == self.getEndDelimiter(): # Change state state = GOT_VCALENDAR # Look for end of current component elif line == compend: # Finalise the component (this caches data from the properties) comp.finalise() # Embed component in parent and reset to use parent componentstack[-1][0].addComponent(comp) comp, compend = componentstack.pop() # Blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("iCalendar data has blank lines") # Ignore top-level items elif comp is self: pass # Must be a property else: # Parse parameter/value for top-level calendar item prop = self.sPropertyType.parseText(line) # Check for valid property if comp is not self: comp.addProperty(prop) # Exit if we have one - ignore all the rest if state == GOT_VCALENDAR: break # We need to store all timezones in the static object so they can be accessed by any date object # Only do this if we read in a timezone if got_timezone: from pycalendar.timezonedb import TimezoneDatabase TimezoneDatabase.mergeTimezones(self, self.getComponents(definitions.cICalComponent_VTIMEZONE)) return result
def setUp(self): TimezoneDatabase.createTimezoneDatabase(None)
def test_isStandardTimezone(self): """ L{TimezoneDatabase.isStandardTimezone} returns correct result when the database cache is initially empty. """ data = ( ("America/New_York", True), ("America/Los_Angeles", True), ("America/Cupertino", False), ("America/FooBar", False), ) TimezoneDatabase.getTimezoneDatabase().clear() # Do twice to excersise the cache for _ in range(2): for tzid, result in data: self.assertEqual(TimezoneDatabase.isStandardTimezone(tzid), result, "Failed {}".format(tzid)) self.assertTrue("America/New_York" in TimezoneDatabase.getTimezoneDatabase().stdtzcache) self.assertTrue("America/Los_Angeles" in TimezoneDatabase.getTimezoneDatabase().stdtzcache) self.assertFalse("America/Cupertino" in TimezoneDatabase.getTimezoneDatabase().stdtzcache) self.assertFalse("America/FooBar" in TimezoneDatabase.getTimezoneDatabase().stdtzcache) self.assertFalse("America/New_York" in TimezoneDatabase.getTimezoneDatabase().notstdtzcache) self.assertFalse("America/Los_Angeles" in TimezoneDatabase.getTimezoneDatabase().notstdtzcache) self.assertTrue("America/Cupertino" in TimezoneDatabase.getTimezoneDatabase().notstdtzcache) self.assertTrue("America/FooBar" in TimezoneDatabase.getTimezoneDatabase().notstdtzcache)