WSL Timezone Synchronization: Keep Wall Clocks and UTC Instants Separate
Configure WSL's Windows timezone synchronization deliberately, then test local-time display separately from clock drift and UTC timestamps.
A Linux process in WSL can display a different local time from Windows even when both systems agree on the underlying UTC instant. That is usually a timezone configuration question, not clock drift. The WSL configuration reference documents a per-distribution [time] setting named useWindowsTimezone, whose default is true; Microsoft describes it as making WSL use and synchronize to the timezone set in Windows. The setting concerns timezone behavior. It is not a general control for clock accuracy, time synchronization servers, or application scheduling.
This distinction matters for build timestamps, cron jobs, database logs, certificates, and incident timelines. Changing a timezone changes how a timestamp is rendered and how local calendar boundaries are interpreted. It should not change the Unix epoch time representing a moment. Diagnose both values before changing configuration.
UTC instant versus local wall-clock representation
Unix time represents elapsed seconds from an epoch and does not encode a local timezone. A formatted value such as 2026-10-03 14:30 -0300 combines an instant with a timezone offset. Two machines can correctly show different wall-clock strings for the same instant if their timezones differ. Conversely, two machines can show the same local clock while disagreeing about the actual instant if one clock is wrong.
For a quick Linux-side comparison, capture both the epoch and the local offset:
date -u '+UTC %Y-%m-%dT%H:%M:%SZ'
date '+LOCAL %Y-%m-%dT%H:%M:%S %Z %z'
date +%s
On Windows, compare the current UTC instant and configured timezone:
[DateTimeOffset]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
Get-TimeZone | Format-List Id, DisplayName, BaseUtcOffset
The output timestamps will not be identical to the millisecond because commands execute at different times. Compare the epoch values within a reasonable measurement interval when diagnosing clock agreement, and compare zone identifiers and offsets when diagnosing display differences. Daylight-saving transitions can make a fixed offset insufficient to identify the intended timezone; use named timezone data and test around transitions relevant to the workload.
Understand the WSL setting’s scope
/etc/wsl.conf is per distribution. Its [time] section can be used to opt out of Windows timezone synchronization:
[time]
useWindowsTimezone=false
The documented default is true, so a distro with no explicit setting normally follows the Windows timezone according to Microsoft’s current reference. The false example means the operator is choosing a Linux-side timezone policy rather than Windows synchronization; the exact mechanism for setting that policy belongs to the distribution and its timezone packages. Do not assume that a particular symlink, /etc/timezone file, or timedatectl command exists in every distro image.
Before making the change, record the WSL package version, Windows build, distro release, and current /etc/wsl.conf. The setting is per distribution, so two distros can intentionally have different policies. Preserve other sections and keys. After editing, stop the target distribution completely so it can reload configuration. Use wsl.exe --terminate <Distro> from Windows for a specific distro; wsl.exe --shutdown stops all running WSL 2 distributions and should be used only when that broader interruption is acceptable.
Inspect the distro’s timezone state
Capture what the running process sees rather than inferring it from Windows settings:
printf 'TZ=%s\n' "${TZ-<unset>}"
date '+%Y-%m-%d %H:%M:%S %Z %z'
date -u '+%Y-%m-%d %H:%M:%S UTC'
readlink -f /etc/localtime 2>/dev/null || true
The TZ environment variable can override system timezone data for a process. A process launched from a shell with a modified environment can therefore differ from an interactive shell, even when the distro’s system configuration is unchanged. Check service manager environment files, shell startup files, containers, and application-specific timezone options before changing WSL-wide behavior.
If systemd is available, timedatectl status may provide useful context, but it is not required for WSL and should not be treated as a universal interface. Minimal containers and imported distros may lack systemd or the timedatectl executable. Use the standard date output and inspect the distro’s timezone database when necessary. Do not manually replace /etc/localtime unless the distro’s documentation supports that method and the effect is understood.
Distinguish timezone mismatch from clock drift
If date -u and Windows UTC differ by a growing interval, investigate timekeeping and resume behavior; a timezone setting will not repair it. If UTC values agree but local output differs, inspect useWindowsTimezone, the active distribution’s timezone setting, and the TZ variable. If the mismatch appears only after sleep or hibernation, follow a clock-drift investigation rather than changing the timezone policy. Keep this distinction in monitoring: compare epoch values for synchronization and local-zone identifiers for display expectations.
Applications may cache timezone data at process startup. After changing timezone configuration, restart the distribution as required, then restart the affected long-running process and check its output. A WSL distro can run systemd services beyond the lifetime of one shell, so closing a terminal window does not guarantee that a service has re-read timezone data. For databases and schedulers, verify the effective timezone from the application’s own diagnostic interface instead of assuming it inherited the shell’s environment.
Plan for daylight-saving and scheduled work
Use UTC for durable event timestamps and cross-system correlation where the application supports it. Convert to local time for user-facing schedules only when the business rule explicitly refers to local civil time. A job scheduled for a local time can encounter skipped or repeated hours when timezone rules change. Test the scheduler’s documented handling of those transitions; do not assume WSL’s Windows timezone synchronization changes the scheduler’s policy.
Keep Windows and Linux timezone databases current through their respective supported servicing processes. The Windows timezone identifier and a Linux zoneinfo name may not share identical spelling, and governments can change timezone rules. Compare actual behavior for a known transition or date rather than hard-coding a numeric offset in scripts. Record the zone name, offset, and UTC instant in incident reports so a future reader can distinguish data from display formatting.
For reproducible builds, decide whether output timestamps should be UTC or local time. Set that policy in the build process explicitly where supported. A developer laptop following Windows local time can produce different human-readable logs from a CI worker configured for UTC without either system having an incorrect clock. Stable machine-readable timestamps should include Z or a numeric offset.
When comparing a Linux service with a Windows client, also inspect the environment inherited by the service. A systemd unit can set Environment=TZ=..., a container can ship a distinct timezone database, and a language runtime can cache a zone rule at startup. Those are independent layers from WSL’s distribution setting. Restart the specific workload after a timezone policy change, then query the workload’s own timestamp formatting or database session setting. Do not use a shell’s output as a proxy for a long-lived process whose environment was created earlier.
For event correlation, preserve the original timestamp and its offset before converting. An ambiguous local time can occur twice during a clock transition; a local string without an offset cannot uniquely identify the instant. If an application requires local civil time, document the timezone name alongside the timestamp and define what happens to a scheduled event during a skipped or repeated interval. WSL synchronizing its timezone does not decide those business semantics for the application.
Acceptance checks
Use a small test matrix: default useWindowsTimezone behavior; an explicit true; and, only if the workload requires it, false with the distro’s own timezone set. Record Windows Get-TimeZone, Linux date -u, Linux date with offset, the WSL package version, and whether the distro was freshly restarted. Verify an application log and scheduler separately if they are the real consumers. Do not assert that a test passed merely because the wall-clock strings match.
Include at least one child process launched through the same route used in production. Windows launching wsl.exe, Linux invoking a Windows program, a systemd service, and a container can inherit different environments. Capture TZ and the formatted timestamp inside the process or its wrapper. If only one process disagrees, investigate that process’s locale, environment, runtime, and cached configuration before changing the distro-wide policy.
For epoch synchronization, compare near-simultaneous UTC readings from Windows and Linux and allow for command execution latency. For timezone synchronization, verify the intended zone and offset on dates on both sides of a daylight-saving transition if relevant. If changing useWindowsTimezone does nothing, verify that the file belongs to the target distro, the key is under [time], the subsystem fully stopped, and the installed WSL version recognizes the setting.
The operational rule is straightforward: use the WSL setting to control whether a distribution follows Windows timezone configuration, use the distro’s supported timezone mechanism when it should be independent, and diagnose UTC clock accuracy separately. That keeps time display, scheduling semantics, and actual clock synchronization from being conflated.
Related:
- Fixing WSL2 Clock Drift After Sleep or Hibernation
- .wslconfig vs. wsl.conf: Two Configuration Scopes That Should Not Be Mixed
Sources: