string(TIMESTAMP out_var %s) timezone issue in Docker environment

System: Ubuntu 18.04 x86_64

I’ve prepared this t.cmake example script:

string(TIMESTAMP t)
string(TIMESTAMP t2 UTC)
string(TIMESTAMP tt %s UTC)
string(TIMESTAMP ttt %s)
message(STATUS "t is ${t}")
message(STATUS "t2 is ${t2}")
message(STATUS "tt is ${tt}")
message(STATUS "ttt is ${ttt}")
execute_process(COMMAND python3 "-c" "import time; t=${tt}; print('python time:', t, time.ctime(t))")
execute_process(COMMAND python3 "-c" "import time; t=time.time(); print('python time:', t, time.ctime(t))")

I downloaded cmake 3.22.5 for Linux from github release page.

On host Ubuntu 18.04, run cmake -P t.cmake got the following, which is normal:

-- t is 2022-06-20T11:38:26
-- t2 is 2022-06-20T03:38:26Z
-- tt is 1655696306
-- ttt is 1655696306
python time: 1655696306 Mon Jun 20 11:38:26 2022
python time: 1655696306.6099617 Mon Jun 20 11:38:26 2022

If I run this in a docker (the image is based on Ubuntu 18.04, but with lots of other stuff added):

-- t is 2022-06-20T11:39:34
-- t2 is 2022-06-20T03:39:34Z
-- tt is 1655725174
-- ttt is 1655725174
python time: 1655725174 Mon Jun 20 19:39:34 2022
python time: 1655696374.068124 Mon Jun 20 11:39:34 2022

The result of getting Unix timestamp does not match that from Python output, actually the “UNIX timestamp” is not UTC, but it’s a seconds value for my local timezone (UTC+0800), passing it to Python’s time.ctime(), which expects UTC timestamp, will print the time 8 hours in the future.

In the meantime, the default timestamp seems to be correct, it’s correct local time.

Then I pulled the official Ubuntu 18.04 docker image, and run a vanilla container from it, installed Python3 in it, and run the test again, the result is right.

So what stuff may affect CMake to produce this incorrect Unix timestamp in my custom Docker container environment? Thanks!

Docker images usually have some default timezone set (probably UTC). You can use timedatectl to control it IIRC.

Not sure if this is related, the docker container is started with this bind mount:
-v /etc/localtime:/etc/localtime:ro

So inside the container, date command reports correct local time, with correct local timezone.

FWIW, it looks like CMake ends up using gettimeofday(2) under the hood (via libuv). There’s also a call to localtime(3) which uses whatever the C library thinks is the current time zone. I don’t remember how that gets influenced off hand.