Jupyter Server 2.0 TZ environment variable affecting kernel timestamp inheritance
0 reputation · 07 Nov 2021, 07:29 UTC
0 reputation · 07 Nov 2021, 07:29 UTC
TZ environment variable has shifted regarding how internal timestamps are handled. When this variable is defined prior to launch, the server adopts this zone for all internal operations, potentially overriding the host's local time settings.This creates a compatibility boundary for notebooks that previously relied on the kernel's locale. While timezone-aware objects in libraries like pandas or datetime remain consistent, naive datetime objects now reflect the server-configured zone rather than the system's local time.
Since kernels inherit the server's environment at startup, there is uncertainty regarding how dynamic changes to os.environ['TZ'] within a cell affect existing processes or whether nbconvert tasks might bypass the server-level setting in favor of the system clock clock.
TZ variable within a running kernel cell affect subsequent naive datetime calls in that same kernel?TZ configuration is ignored by scheduled nbconvert executions?26525 reputation · 07 Nov 2021, 11:35 UTC
os.environ['TZ'] inside a running kernel cell affect subsequent naive datetime calls? No, not automatically. datetime.datetime.now() relies on the C library’s time zone state, which is set once when the Python process starts. Changing TZ after that requires a re‑initialisation call.TZ is ignored by scheduled nbconvert runs? Yes. If nbconvert is launched as a separate process (e.g., via a cron job, JupyterHub spawner, or a manual command line call), it inherits the environment of the shell that started it, not the Jupyter Server’s environment. In those cases, the server’s TZ setting is bypassed and the system default TZ is used.Python’s datetime module is a thin wrapper around the host operating system’s C time functions. When the interpreter starts, it calls tzset() (Unix only) to load the time zone information from the TZ variable. Subsequent calls to datetime.now() use that cached state. Simply assigning a new value to os.environ['TZ'] does not trigger a new tzset() call, so the kernel continues to use the original zone.
jupyter nbconvert will use the environment of that service, not the Jupyter Server’s.jupyter nbconvert from a shell that hasn’t exported TZ will default to the system TZ.TZ, causing nbconvert (which inherits from the container) to use the host’s TZ.%env TZ
import os, datetime, time
print('TZ in env:', os.environ.get('TZ'))
print('Now:', datetime.datetime.now())
import os, time
os.environ['TZ'] = 'UTC'
time.tzset() # re‑initialise C library
print('Now after tzset:', datetime.datetime.now())
If you see the new zone reflected, the change worked.kernel.json (or launching Jupyter with --env TZ=…):
{
"argv": ["python", "-m", "ipykernel_launcher", "-f", "{connection_file}"],
"display_name": "Python 3",
"env": {"TZ": "America/New_York"}
}
After restarting the kernel, the new TZ is part of the process environment from the start.TZ=America/New_York jupyter nbconvert --to html mynotebook.ipynb.TZ in the job’s environment or pass it via the --env flag of the Jupyter spawner.ps -o pid,cmd -p $(pgrep -f "nbconvert")
Check that TZ appears in the command line or environment dump.To fine‑tune the recommendation, it would help to know the operating system you’re running (Unix vs Windows) because time.tzset() is not available on Windows. If you’re on Windows, the only way to change the zone for the current process is to restart the kernel with a new TZ in kernel.json or to set it before launching Jupyter.
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 07 Nov 2021, 10:49 UTC
To build on the point regarding the C library's cached state, it is important to note that while modifying os.environ['TZ'] alone is insufficient, the time module provides a mechanism to force a refresh on Unix-based systems.
If you need to change the timezone for naive datetime calls within a running kernel without restarting, you can call time.tzset() immediately after updating the environment variable:
import os
import time
from datetime import datetime
os.environ['TZ'] = 'America/New_York'
time.tzset() # Updates the C library's internal timezone state
print(datetime.now())
Verification Note: This approach is specific to Unix/Linux environments. On Windows, time.tzset() is not available, and naive datetime objects will typically continue to follow the system's local time regardless of the TZ environment variable. For cross-platform consistency, using timezone-aware objects via datetime.timezone or zoneinfo (Python 3.9+) is the recommended practice.