Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows local time zone should be mapped into WSL properly #3747

Closed
mattjohnsonpint opened this issue Jan 1, 2019 · 12 comments
Closed

Windows local time zone should be mapped into WSL properly #3747

mattjohnsonpint opened this issue Jan 1, 2019 · 12 comments
Assignees

Comments

@mattjohnsonpint
Copy link

mattjohnsonpint commented Jan 1, 2019

As touched on in #856, #1392, and #3109 (without resolution), WSL doesn't correctly map the local time zone of Windows into Linux. Instead, LsxxManager creates a pseudo time zone in /usr/share/zoneinfo/Msft/localtime, and hard links it to /etc/localtime.

This approach is problematic. Though it gets the current time correct, it removes a ton of detail about the time zone, such as its identifier, abbreviations, historical and future transitions (if they deviate from those in the current year), etc. It also removes any ability for downstream APIs (such as ICU) to generate a correct display name.

This is seen in many environments, but perhaps the easiest is in Node JS. Install the latest Node LTS (I'm on 10.15.0) into a regular (non-WSL) Windows environment and also into WSL. Then in the Node command line:

console.log(new Date().toString())
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

In a regular environment, with my computer's time zone set for US Pacific Time, I get:

Mon Dec 31 2018 15:45:41 GMT-0800 (Pacific Standard Time)
America/Los_Angeles

In a WSL environment (for me, Ubuntu 18.04.1 LTS), I get:

Mon Dec 31 2018 15:45:41 GMT-0800 (GMT-08:00)
undefined

It can also be seen just on the Linux command line:

date +%Z

For me running this in December, it should return PST, but in WSL it returns STD because that is the abbreviation assigned in the pseudo zone.

Additionally - the pseudo zone is not necessary. Windows already has the ability to generate the Linux (IANA) time zone identifier, via either of two mechanisms:

  • Call the WinRT/UWP function: Windows::Globalization::Calendar().GetTimeZone() (docs here)

  • The above function uses the data file at %WINDIR%\Globalization\Time Zone\timezoneMapping.xml. It can be used directly if WinRT/UWP is not available. The entry to use is the one with Region="001" and a WinID corresponding to the output from GetDynamicTimeZoneInformation->TimeZoneKeyName (or from the registry at HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\TimeZoneKeyName). The Linux time zone ID is in the TZID field.

Once the Linux time zone ID is known, then /etc/localtime should simply be symlinked to the corresponding file in /usr/share/zoneinfo. If it doesn't exist (perhaps on certain versions of Linux without a tzdata distribution), then and only then should it fall back to the pseudo Msft time zone.

Please revisit this asap. Thanks.
(I can be reached internally at ms alias mattjoh if you have any additional questions)

@mattjohnsonpint
Copy link
Author

Note, #3109 describes how the MSFT zone shows up on .NET Core:

TimeZoneInfo.Local.DisplayName:                          GMT
TimeZoneInfo.Local.Id:                                   Msft/localtime

Again, if mapped correctly, these APIs would just work.

@benhillis
Copy link
Member

Thanks for the detailed post, @mj1856. Agreed, this is something that should be revisited.

@benhillis benhillis self-assigned this Jan 2, 2019
@jefgen
Copy link
Member

jefgen commented Jan 2, 2019

Thanks for filing this issue!
I just wanted to add that another potential option, if you can't call any WinRT/UWP functions for some reason, is to call the flat C API ucal_getDefaultTimeZone in order to get the mapped IANA time zone identifier. (Note that this API is only available if you are on RS2+ though).

@mattjohnsonpint
Copy link
Author

@jefgen - Thanks! I didn't know about that one.

@therealkenc
Copy link
Collaborator

^--- Awesome Ben (Christmas in January 🎉). @mj1856 please do drop us a visit again sometime and do one for locale.

@SRGOM
Copy link
Contributor

SRGOM commented Jan 26, 2019

Everybody take note-- this is how your make issues :)

@benhillis
Copy link
Member

The new implementation is in 18344, I hope it ticks all the boxes for you :)

@mattjohnsonpint
Copy link
Author

Thanks! I'll take a look at some point. ;)

@chetgurevitch
Copy link

Hi, it seems like the fix for this breaks things for people using utc on windows (dual booters), which can be done with a registry key like so

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_QWORD /f

I'm not even sure if the above is something officially supported, but with windows set to utc wsl2 still runs the conversion from localtime, meaning my clock ends up 7 hours fast.

@mattjohnsonpint
Copy link
Author

@chetgurevitch, could you please open a separate issue for that problem so it doesn't get lost? Thanks.

@BrianInglis
Copy link

RealTimeIsUniversal refers only to the RTC setting being UTC rather than local, and should have no influence on Windows timekeeping after boot, and should make it easier as WSL RTC virtualization should not have to backconvert to UTC at Unix boot.
I've been running with that setting for over a decade to make life easier for Windows time sync utilities, mainly NTP (Meinberg build mostly) with my Garmin 18x LVC GPS, after the old NTP "compatible" Windows Time Sync Service was downgraded to the current implementation.
[Syncing system time since DataStorm Procomm-Plus to NIST ACTS dialup.]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants