regebro / tzlocal

A Python module that tries to figure out what your local timezone is

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ValueError: Timezone offset does not match system offset: 0 != 3600. Please, check your config files.

AtomBaf opened this issue · comments

Hi @regebro

I'm experiencing a problem using the library with the latest version 4.1 from within a docker container.

After investigation, I discovered that the library is trying to guess the local timezone by looking at the file name targeted by the symlink /etc/localtime (Linux, Centos 8)

To reproduce:

>docker run -v /etc/localtime:/etc/localtime:ro --rm centos:8 ls -la /etc/localtime
lrwxrwxrwx. 1 root root 25 Sep 15 16:17 /etc/localtime -> ../usr/share/zoneinfo/UTC

This type of mount is a very common way of setting the timezone of the container and avoid defining a TZ env variable.

Guessing the content of the file with its name (or the name of the linked file) is probably questionable. It would be much cautious to read the content.

Thanks in advance

It's not "guessing" the timezone. It's looking up the timezone configuration. In your case it's set to UTC, but it seems some other part of your system disagree.

This is basically what I'm telling, the library is guessing the local timezone name by parsing the symlink target name ref. This looks wrong since:

  • nothing prevent a user to name the target file with an arbitrary string, and still, it will be a valid setting
  • inside a docker container with the mount I describe, the result will be UTC even if the host has another setting

Proof (on a centos7 host)

# checking the host localtime setting
> ls -la /etc/localtime                                                             
lrwxrwxrwx. 1 root root 35 Dec 18  2019 /etc/localtime -> ../usr/share/zoneinfo/Europe/Zurich
# checking the host date, all ok
> date                                                                              
Sat Apr  2 18:53:49 CEST 2022
# now start a docker container with the rightful /etc/localtime mount
> docker run -v /etc/localtime:/etc/localtime:ro -it --entrypoint bash python:latest
# checking the localtime settings, you see it's a symlink with a name UTC
root@8fabc099d223:/# ls -la /etc/localtime 
lrwxrwxrwx. 1 root root 27 Mar 28 02:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
# but thanks to the content of the file which is managed by docker the date is ok
root@8fabc099d223:/# date
Sat Apr  2 18:54:07 CEST 2022
root@8fabc099d223:/# pip install tzlocal
...
# and here is the culprit
root@8fabc099d223:/# python -c "import tzlocal; print(tzlocal.get_localzone())"
Etc/UTC

Sorry but guessing the local time zone by parsing the name of a file instead of its content is probably wrong.

PS: from within the same container:

>python -c "from datetime import datetime; print(datetime.utcnow().astimezone().tzinfo)"
CEST

"nothing prevent a user to name the target file with an arbitrary string, and still, it will be a valid setting"

And then it will break.

There is no official standard way to figure out the time zone name on Unix that will work on all unices. You can call looking at the configuration "guessing" if you want to, but it doesn't change anything. The whole purpose of tzlocal is to figure out the local timezone from the various configurations available.

If these conflict with each other, an error will occur, as it means it could not figure it out.

The way to solve that is to either fix the configuration, or force it by setting a TZ environment, because then it will ignore the other configurations.

Ok, so a dug a bit in the arcanes of systemd, localtime(5) and timedatectl(1).
I was wrong since I found this source code. It is doing exactly the same logic as tzlocal to find the current timezone name (with the name of the symlink).

Now, I'm a bit puzzled since a lot (talking about hundreds) of my docker containers are running with the mount I described. I will change them to use a TZ env variable instead. It will work with tzlocal but maybe not with other programs.
Probably the solution is to use both settings (TZ + bind mount /etc/localtime), which I find ackward, but that's fine.

Thanks for your help

Yeah, I find it very curious that the docker setup (if I understand you correctly) overwrites the Etc/UTC file. I'm guessing this is because /etc/localtime is a link, and the "-v" argument doesn't overwrite the file itself, but for some reason expands the link before mounting the local file.

Another option is to set a timezone explicitly in another configuration file. But it's probably easier to just set a global TZ in the docker container. Or perhaps just let the docker container run on UTC?

expands the link before mounting the local file

you're absolutely right

just let the docker container run on UTC

not an option in my case

It's a pitty in 2022 that we still have to deal with tz things without having just one way to do so. I guess that when DST will be abandoned (Nov 2023 in USA?) it will trigger a new massive y2k bug on a lot of configs.

thx