Skip to content

Instantly share code, notes, and snippets.

@medmunds
Created May 28, 2016 19:05
Show Gist options
  • Save medmunds/d519841774414ba21a53d9d180dff9ca to your computer and use it in GitHub Desktop.
Save medmunds/d519841774414ba21a53d9d180dff9ca to your computer and use it in GitHub Desktop.
Compare vobject VTIMEZONEs for pytz and dateutil.tz timezones
# Detect differences between pytz and dateutil.tz.gettz,
# by comparing the vobject VTIMEZONEs for each.
#
# (Might actually be finding problems in vobject's
# timezone rule detection.)
#
# Requirements::
# pip install pytz dateutil vobject
import dateutil.tz
import os
import pytz
from vobject.icalendar import TimezoneComponent, __tzidMap
OUTPUT_DIR = '/tmp/vtimezone' # set to None to skip writing files
#OUTPUT_DIR = None
def vtimezones_match(tzname, output_dir=None):
"""Returns True if pytz and dateutil have same VTIMEZONE for tzname.
Set output_dir to write mismatched VTIMEZONE contents to files,
allowing easy directory diff. (Will create one file in output_dir/pytz,
and a corresponding file in output_dir/dateutil.)
"""
pytz_tzinfo = pytz.timezone(tzname)
dateutil_tzinfo = dateutil.tz.gettz(tzname)
# ignore differences in TZID field (see TimezoneComponent.pickTzid)
pytz_tzinfo.tzid = dateutil_tzinfo.tzid = tzname
__tzidMap.clear() # reset tzid registry to avoid caching
pytz_vtimezone = TimezoneComponent(tzinfo=pytz_tzinfo)
pytz_serialized = pytz_vtimezone.serialize()
__tzidMap.clear() # reset tzid registry to avoid caching
dateutil_vtimezone = TimezoneComponent(tzinfo=dateutil_tzinfo)
dateutil_serialized = dateutil_vtimezone.serialize()
matches = (pytz_serialized == dateutil_serialized)
if output_dir and not matches:
# Relies on tzname using slash separators
write_file(
os.path.join(output_dir, 'pytz', tzname),
pytz_serialized)
write_file(
os.path.join(output_dir, 'dateutil', tzname),
dateutil_serialized)
return matches
def write_file(path, text):
"""Writes text to path, creating intermediate dirs if needed"""
dirname = os.path.dirname(path)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(path, 'w') as f:
f.write(text.replace('\r\n', '\n'))
def get_dateutil_tzdb_version():
"""Return the version of the tzdb files used by dateutil.tz.gettz"""
# From the contents of the +VERSION file in the tzdb directory
utc = dateutil.tz.gettz('UTC')
tzdb_dir = os.path.dirname(utc._filename)
version_file = os.path.join(tzdb_dir, '+VERSION')
with open(version_file) as f:
version = f.read()
return version.strip()
if __name__ == '__main__':
dateutil_version = "%s; tzdb %s" % (dateutil.__version__,
get_dateutil_tzdb_version())
print("pytz version: %s" % pytz.__version__)
print("dateutil version: %s" % dateutil_version)
if OUTPUT_DIR:
write_file(os.path.join(OUTPUT_DIR, 'pytz/VERSION'), pytz.__version__)
write_file(os.path.join(OUTPUT_DIR, 'dateutil/VERSION'), dateutil_version)
print("\nDiffering VTIMEZONEs:")
for tzname in pytz.all_timezones:
if not vtimezones_match(tzname, output_dir=OUTPUT_DIR):
print(tzname)
pytz version: 2016.4
dateutil version: 2.5.3; tzdb 2016d
Differing VTIMEZONEs:
America/Argentina/Catamarca
America/Argentina/ComodRivadavia
America/Argentina/La_Rioja
America/Argentina/Mendoza
America/Argentina/Rio_Gallegos
America/Argentina/San_Juan
America/Argentina/San_Luis
America/Argentina/Tucuman
America/Argentina/Ushuaia
America/Cambridge_Bay
America/Catamarca
America/Indiana/Knox
America/Indiana/Petersburg
America/Indiana/Tell_City
America/Indiana/Vincennes
America/Indiana/Winamac
America/Knox_IN
America/Mendoza
America/Rankin_Inlet
America/Resolute
Asia/Anadyr
Asia/Kamchatka
Asia/Khandyga
Asia/Novokuznetsk
Asia/Tbilisi
Asia/Tomsk
Europe/Samara
US/Indiana-Starke
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment