swiftlang/swift-foundation

[Windows] TimeZone.current returns GMT despite system settings

Closed this issue · 2 comments

Running TimeZone.current on Windows always returns GMT despite any present system settings.

This appears to be because on Windows we check TZDEFAULT:

#if os(Windows)
let hFile = TZDEFAULT.withCString(encodedAs: UTF16.self) {
CreateFileW($0, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nil, OPEN_EXISTING, 0, nil)
}
defer { CloseHandle(hFile) }
let dwSize = GetFinalPathNameByHandleW(hFile, nil, 0, VOLUME_NAME_DOS)
let path = withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwSize)) {
_ = GetFinalPathNameByHandleW(hFile, $0.baseAddress, dwSize, VOLUME_NAME_DOS)
return String(decodingCString: $0.baseAddress!, as: UTF16.self)
}
if let rangeOfZoneInfo = path._range(of: "\(TZDIR)\\", anchored: false, backwards: false) {
let name = path[rangeOfZoneInfo.upperBound...]
if let result = fixed(String(name)) {
return TimeZone(inner: result)
}
}

However, TZDEFAULT does not appear to be set in the WinSDK/ucrt modules so we instead pickup the default value from our CShims:

#ifndef TZDIR
#define TZDIR "/usr/share/zoneinfo/" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */

These default paths seem unsuitable for Windows and result in us failing to detect the current timezone and falling back to GMT

@compnerd do you happen to know if we'd expect TZDEFAULT to be defined for Windows somewhere, or do we need to instead do something like what CoreFoundation has historically done: https://github.com/swiftlang/swift-corelibs-foundation/blob/e55e1d88001997be830fbc01086564431d405dad/Sources/CoreFoundation/CFTimeZone.c#L723-L734

I don't expect TZDEFAULT to be set on Windows, we should be doing what CF did historically here.