Improved SFTP file UTC time handling #1
Merged
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.
I changed SftpFileAttributes to preserve the last access and modified times as UTC values rather than always forcing a local conversion. This primarily affected the FromBytes(SshDataStream) method, but the changes cascade out from there to make sure that SftpFileAttributes and SftpFile can be used without ever forcing a (potentially lossy) conversion to local time. In the SSH data stream the atime and mtime values are "Unix times" in seconds, so they're already in UTC. We need to preserve that fact by returning and storing DateTime values with Kind == Utc.
Previously, the code called DateTime.FromFileTime. Internally, FromFileTime calls DateTime.ToLocalTime(), which is a lossy function. For example, any local time >= 1am and < 2am during the "fall back" hour of a daylight saving time shift in the fall could have come from two different UTC times. Avoiding this ambiguity is why file systems store times in UTC, so the SFTP classes need to preserve UTC times too. Here's a simple example to see this in VS's C# interactive window:
.NET also has an issue where it caches the current local time zone offset, so it can incorrectly calculate local times after a DST shift if nothing has called CultureInfo.ClearCachedData or TimeZoneInfo.ClearCachedData. This is discussed more at https://stackoverflow.com/a/297189/1882616, and it can be a big problem in long-running services if not handled correctly. By making SSH.NET internally preserve UTC times correctly, the library can be immune to problems with DST shifts for callers that only work with UTC times.
I also cleaned up some warnings in the unit tests and added an .editorconfig file so VS 2017 will know to use spaces for indentation in this solution (even though my global preference is set to tabs).