GetFileAttributesEx returns the date that the filesystem returns, unmodified. NTFS stores dates in UTC, and FAT stores them in the local time zone. Without knowing the time zone, a date is pretty worthless.
What is the best way to reliably get the last modified date of a file in UTC? Is the best way really to just check for NTFS vs. FAT? What if you are using a different filesystem? Is there a different API I can use? Is there some elegant code someone can post here?
Use the Win32 API GetFileTime, it returns all its times in UTC. Yes, FAT file system does store these values in local time, but the Win32 API is doing the UTC conversion for you.
Quote from the 'FileTimes' MSDN documentation:
GetFileTime retrieves cached UTC times from the FAT file system.
from http://msdn.microsoft.com/en-us/library/ms724290%28v=vs.85%29.aspx
The FAT file system records times on disk in local time. GetFileTime retrieves cached UTC times from the FAT file system. When it becomes daylight saving time, the time retrieved by GetFileTime is off an hour, because the cache is not updated. When you restart the computer, the cached time that GetFileTime retrieves is correct. FindFirstFile retrieves the local time from the FAT file system and converts it to UTC by using the current settings for the time zone and daylight saving time. Therefore, if it is daylight saving time, FindFirstFile takes daylight saving time into account, even if the file time you are converting is in standard time.
Related
Go version: 1.14.2
Operating system: Linux (Ubuntu)
I am working on a dynamic timezone based system in which user can set the timezone. I have a user who set the timezone to US/Pecific-New. For this timezone, the golang time package gives following error:
unknown time zone US/Pacific-New
I have researched on this and found that time package loads the timezone from the local system having file paths:
/usr/share/zoneinfo
/usr/local/go/lib/time
On these paths, on my local system as well as on staging Pacific-New is missing on both locations.
Is there a way to get Pacific-New on these locations ?
US/Pacific-New was never a "real" time zone and should not be selected on any system.
It was created to reflect a potential change to Pacific time that was never enacted into law. The idea at the time was that there would be a time zone ready in advance of the change. However, since the bill wasn't enacted this turned out to be a failed experiment. The TZDB no longer tries to create zones in speculative anticipation of future changes, but only adds or updates them when they are official or otherwise imminent.
Ultimately, US/Pacific-New was only ever a link to US/Pacific and then later updated as a link to the preferred form of America/Los_Angeles The last TZDB release to include such a link for US/Pacific-New was 2020a.
From the 2020b release notes:
The long-obsolete files pacificnew, systemv, and yearistype.sh have been removed from the distribution. (Thanks to Tim Parenti.)
You can read more about the long storied history with this link entry by searching the NEWS file in the TZDB for "Pacific-New" and "pacificnew", and by reading the 2020a version of the pacificnew file from before it was deleted.
As far as practical advice, don't set US/Pacific-New on any system. It is no longer a valid time zone identifier. The whole system will be affected by this. Switch to America/Los_Angeles instead.
Rather than time.LoadLocation() you can use time.LoadLocationFromTZData() which loads a location from the contents of a timezone file, which can contain whatever timezones you like.
You will need a correctly formatted timezone file with the timezones you wish to use, perhaps based on whatever you have in /usr/share/zoneinfo.
I am trying to get the last shutdown time of the system. I tried event log EvtQuery() method and got the value Event/System/TimeCreated/#SystemTime but it is not accurate.
I need this Time and date value:
I got value only from here, dates are the same but time is different:
Your timestamps do match, but one is in UTC (17:21:34) the other in local time (10:51:34 PM -> 22:51:34).
So it looks like your local timezone is 5:30 ahead of UTC time. So according to wikipedia that would be parts of India or Sri Lanka.
So what you have to do is convert the local time value to UTC (or the other way around) and you should see that they are the same.
There should be plenty of material for this on StackOverflow (try this search for example).
I would like to know when a Location's offset from UTC is going to change. I see that this information is known by the time package, obviously or it wouldn't be able to account for daylight savings. That way I could find out that for the location "America/New_York" daylight savings begins on Sunday, March 11 2018 at 07:00 UTC.
Is there a way to do this short of making my own copy of the time package that exports the Location properties or writing my own parser for the time zone files?
As you've seen in the source, no, that information is not exposed. But, as you can also see from the source, the raw TZDB used to generate the timezones is included in the Go distribution:
//go:generate env ZONEINFO=$GOROOT/lib/time/zoneinfo.zip go run genzabbrs.go -output zoneinfo_abbrs_windows.go
If you take a look at your $GOROOT/lib/time you'll find that file, which contains all the data used to generate the time zone list, and you can look at $GOROOT/src/time/genzabbrs.go to see how it's used.
I ran into an issue with Go code, related to time zones, that would return either 1900-01-01 01:00:00 +0100 CET or 1900-01-01 00:53:28 +0053 LMT, depending on which machine it is being run:
https://play.golang.org/p/K3ceq1n1KI
I was able to rule out the Go version as source of the difference. Where does Go get its time zone information from?
Actually it depends.
Check time.LoadLocation() source and the comment above it. Particularly, it says this:
// LoadLocation looks in the directory or uncompressed zip file
// named by the ZONEINFO environment variable, if any, then looks in
// known installation locations on Unix systems,
// and finally looks in $GOROOT/lib/time/zoneinfo.zip.
And you should keep in mind that on a Unix/Posix systems (e.g. Linux), proper time zone data files are always available in "known installation locations". But on other systems there no such locations. As a result, on Windows, LoadLocation zone won't find any time zones (unless either ZONEINFO or GOROOT were configured properly) and will just use default instead (which is UTC, if my memory is correct).
However, the LMT issue you described above is a bit different beast. You see, LMT is not exactly a proper time zone. E.g. see here. And I didn't dig out where exactly it comes from, but I suspect it is related to the fact that the time zone was not established yet at the time that you're converting. So, go seems to be calculating LMT of the place instead.
For example, if you just change year from 1900 to 2000 (or even 1905) in your playground example, it will come out with correct time zone (CET).
As to the difference between machines, I'd say it's pretty arguable what is the most natural way of defining time zone rules before they were actually introduced. As a result, I would imagine that in some time zone databases, start time of the first rule in a time zone will be either omitted or adjusted to extend it further to the past. While others will put an LMT offset there instead. (Even though most if not all of them are derived from the same IANA database in one way or another.)
If you want to ensure exact same behavior on different machines, I'd say building your own zoneinfo.zip and setting ZONEINFO variable should help.
I'm attempting to convert a time from UTC to the Phone's local time. For this I'm using the following:
if (progress.ActionDateTime.HasValue)
progress.ActionDateTime = TimeZoneInfo.ConvertTime(progress.ActionDateTime.Value, TimeZoneInfo.Local);
However, the time remains exactly the same after the conversion has took place. Is this method working in WP7?
A DateTime does not store information about the time zone. According to the documentation, TimeZoneInfo.ConvertTime will use the DateTime.Kind property to determine how the time should be converted:
DateTimeKind.Local and DateTimeKind.Unspecified: Converts the local time to the time in destinationTimeZone.
DateTimeKind.Utc: Converts Coordinated Universal Time (UTC) to the time in destinationTimeZone.
Since you're using TimeZoneInfo.Local for the second parameter (which specify the destination time zone), I'm assuming that you're DateTimeKind is either Local or Unspecified. Therefore, you're converting a local date to a local date, which obviously won't work.
DateTime.ToLocalTime also uses the DateTimeKind. According to the documentation:
Utc: This instance of DateTime is converted to local time.
Local: No conversion is performed.
Unspecified: This instance of DateTime is assumed to be a UTC time, and the conversion is performed as if Kind were Utc.
Basically, while TimeZoneInfo.ConvertTime considers that DateTimeKind.Unspecified = Local, DateTime.ToLocalTime considers that DateTimeKind.Unspecified = Utc. It explains why the latter works while the former doesn't.