Closed asottile closed 5 years ago
I'm not sure what "empty" means when it comes to docker. It should reasonably have SOME sort of time zone configuration?
I fiddled round a bit and I think having TZ set, but to an empty string, could be the cause of this behavior.
empty in that I haven't installed anything
there isn't a TZ
variable set, here's the contents of the environment:
$ docker run --rm ubuntu:bionic env | sort
HOME=/root
HOSTNAME=7e1433ab994c
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
or from a shell:
$ docker run --rm ubuntu:bionic bash -c env | sort
HOME=/root
HOSTNAME=bfc808504f4b
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
_=/usr/bin/env
or from an interactive login shell:
$ docker run --rm -ti ubuntu:bionic bash -ilc env | sort
HOME=/root
HOSTNAME=40ebadebee99
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
TERM=xterm
_=/usr/bin/env
I can confirm this. tzlocal.get_localzone()
raises an exception in a ubuntu:bionic
container w/ nothing added to it except Python 3 & tzlocal
.
The difference between the bionic
and xenial
(the preceding Ubuntu LTS) containers seems to be that bionic
lacks both /etc/localtime
and /etc/timezone
. Without those, tzlocal
raises.
The readme also states,
Any unix-like system with a /etc/localtime or /usr/local/etc/localtime
If I copy the /etc/localtime
from Xenial into the Bionic container, tzlocal
still raises. On Xenial, it's a symlink:
lrwxrwxrwx 1 root root 27 Jan 23 2018 localtime -> /usr/share/zoneinfo/Etc/UTC
Now, it's also a broken symlink in Xenial. It's adding /etc/timezone
that actually works for me in Bionic. (Which is a text file whose content is a zone name followed by a newline.) So I suspect on both Xenial, tzlocal
ignores the broken symlink, and gets the information from /etc/timezone
.
I agree w/ @asottile: the README suggests this should work. Additionally, glibc/C programs can get the timezone just fine; glibc seems to default to UTC in the presence of no config files and no environment variables. I think tzlocal
should mirror glibc
's behavior here. That is, the following:
#define _GNU_SOURCE /* for tm_gmtoff and tm_zone */
#include <stdio.h>
#include <time.h>
/* Checking errors returned by system calls was omitted for the sake of readability. */
int main(void)
{
time_t t = time(NULL);
struct tm lt = {0};
struct tm *result = localtime_r(&t, <);
if(!result) { printf("localtime_r() error."); }
printf("Offset to GMT is %lds.\n", lt.tm_gmtoff);
printf("The time zone is '%s'.\n", lt.tm_zone);
return 0;
}
Runs on bionic; it emits,
# ./tztest
Offset to GMT is 0s.
The time zone is 'UTC'.
…while tzlocal
raises.
Empty ubuntu:bionic
doesn't ship with the tzdata
package by default (which is where those files come from), whereas ubuntu:xenial
does
So, in fact, an empty ubuntu:bionic doesn't have any timezone configuration. Crazy....
Anyway, I actually use docker in my new job, I'll try to get time to verify this. If there really is no config, then the only way out of this is to have a default when no config is found, and I really don't want to do that.
Try edit the container and then create a environment variable
name = TZ value = your time zone eg America/Toronto
Would be cool if someone that had this issue in real life can test this out from master before I release it.
Using a tweaked reproduction of above:
$ docker run --rm -ti ubuntu:bionic bash -euxc 'apt-get update -qqq && DEBIAN_FRONTEND=noninteractive apt-get install -qqq -y --no-install-recommends python3-pip python3-setuptools git ca-certificates && pip3 install git+https://github.com/regebro/tzlocal && python3 -c "import tzlocal; tzlocal.get_localzone()"'
...
+ pip3 install git+https://github.com/regebro/tzlocal
Collecting git+https://github.com/regebro/tzlocal
Cloning https://github.com/regebro/tzlocal to /tmp/pip-ja8wz1tp-build
Collecting pytz (from tzlocal==2.0.0.dev0)
Downloading https://files.pythonhosted.org/packages/3d/73/fe30c2daaaa0713420d0382b16fbb761409f532c56bdcc514bf7b6262bb6/pytz-2019.1-py2.py3-none-any.whl (510kB)
100% |################################| 512kB 1.7MB/s
Installing collected packages: pytz, tzlocal
Running setup.py install for tzlocal ... done
Successfully installed pytz-2019.1 tzlocal-2.0.0.dev0
+ python3 -c 'import tzlocal; tzlocal.get_localzone()'
/usr/local/lib/python3.6/dist-packages/tzlocal/unix.py:158: UserWarning: Can not find any timezone configuration, defaulting to UTC.
warnings.warn('Can not find any timezone configuration, defaulting to UTC.')
OK, that looks good. Thanks!
I'm not sure what to expect, the readme leads me to believe
that I shouldn't get a crash.
Here's a reproduction with docker:
The timezone in the container is UTC: