regebro / tzlocal

A Python module that tries to figure out what your local timezone is
MIT License
184 stars 58 forks source link

Look up timezone in current directory #71

Closed randomstuff closed 5 years ago

randomstuff commented 5 years ago

If for some reason a file exists in the current directory with the same name as the time zone, it will be used instead of the pytz one:

$ echo "from tzlocal import get_localzone; get_localzone() " | TZ=Europe/Paris strace python3 2>&1 | grep Paris
openat(AT_FDCWD, "/usr/share/zoneinfo/Europe/Paris", O_RDONLY|O_CLOEXEC) = 3
stat("Europe/Paris", 0x7ffe7e270f60)    = -1 ENOENT (No such file or directory)
stat("/usr/share/zoneinfo/Europe/Paris", {st_mode=S_IFREG|0644, st_size=2971, ...}) = 0
openat(AT_FDCWD, "/usr/share/zoneinfo/Europe/Paris", O_RDONLY|O_CLOEXEC) = 3
stat("/usr/share/zoneinfo/Europe/Paris", {st_mode=S_IFREG|0644, st_size=2971, ...}) = 0
openat(AT_FDCWD, "/usr/share/zoneinfo/Europe/Paris", O_RDONLY|O_CLOEXEC) = 3

The reason is this code:

# TZ specifies a file
if os.path.exists(tzenv):
    with open(tzenv, 'rb') as tzfile:
        return pytz.tzfile.build_tzinfo('local', tzfile)

# TZ specifies a zoneinfo zone.
try:
    tz = pytz.timezone(tzenv)
    # That worked, so we return this:
    return tz
except pytz.UnknownTimeZoneError:
    raise pytz.UnknownTimeZoneError(
        "tzlocal() does not support non-zoneinfo timezones like %s. \n"
        "Please use a timezone in the form of Continent/City")

The pytz.tzfile.build_tzinfo('local', tzfile) should probably be limited to absolute paths (if os.path.isabs(tzenv)).

This would mimic the behaviour of GNU libc:

if (__libc_enable_secure
  && ((*file == '/'
    && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
    && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
    || strstr (file, "../") != NULL))
  /* This test is certainly a bit too restrictive but it should
  catch all critical cases.  */
  goto ret_free_transitions;