windows: fix filetime conversions and deprecate Nanoseconds #251
+73
−17
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Filetime.Nanoseconds() has a major drawback: the returned int64 is too small to represent Filetime's zero value (January 1, 1601, [1]) in terms of nanoseconds since Epoch (00:00:00 UTC, January 1, 1970); MinInt64 [2] only dates back to year 1677.
This has real-life implications, e.g., some Windows sub systems (Perflib, to name one) create registry keys with the last write time property set to zero (see note below). In this case, ModTime() reports an underflow-affected value of 2185-07-22T00:34:33.709551+01:00.
This commit deprecates Nanoseconds() in favor of the new Unix() that returns a well-known pair of seconds and nanoseconds [3] thus is capable to cover the full range of Filetime values. ModTime() uses Unix() accordingly to produce correct time.Time values again. Additionally, ModTimeZero() provides a convenient way to check for a last write time value of zero in analogy to time.Time.IsZero() [4]; no need to specify January 1, 1601 manually.
A note on last write time values:
lastWriteTime
is not exposed in the UI (say,regedit
) or in PowerShell (Get-ItemProperty
), you need to queryRegQueryInfoKeyA
[5] explicitly in some way [6] or another [7]. The source of the latter is offline by now but can be found elsewhere [8] and provides a quick way to show the value.[1] https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
[2] https://pkg.go.dev/math#pkg-constants
[3] https://pkg.go.dev/time#Unix
[4] https://pkg.go.dev/time#Time.IsZero
[5] https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryinfokeya?redirectedfrom=MSDN
[6] https://learn.microsoft.com/en-us/windows/win32/sysinfo/retrieving-the-last-write-time
[7] https://learn-powershell.net/2014/12/18/retrieving-a-registry-key-lastwritetime-using-powershell/
[8] https://github.com/wxrdnx/GetRegistryKeyLastWriteTimeAndClassName