How to fix the bogus daylight behavior of DateTime.FromFileTime()

There is an important difference in the way the DateTime.FromFileTime(…) method adjusts for daylight changes versys the rest of the Win32 world. This thing can be truly confusing if you are not aware about the problem. The cause is pretty subtle, and explained in Raymond’s blog. Here are the two behaviors, side by side:

1) The DateTime.FromFileTime(…) considers the daylight changes at the time passed in the FILETIME input parameter. This was needed to keep backward compatibility with the old Visual Basic behavior. While this will work somewhat for the 95% of cases (as Windows tries to figure it out from the user settings), it will horribly fail in the rest of 5%, because you simply cannot figure out the required daylight changes for a given timestamp and a time zone. There are too many exceptions, sometimes tied to political or religious causes, and there are no algorithmic rules there. For example, until 2005, in Israel, the Ministry of Interior decided every year the daylight savings interval.

2) In contrast, Win32 APIs like FileTimeToLocalFileTime always uses the current time (and the current user settings) to establish the daylight corrections. This method has the slight disadvantage that, for the timestamps in the past you apply the current daylight savings. For example, if you right-click a certain file in explorer and inspect its date/time, you will see a different timestamp if you look to the file in December, or if you look to the file in August. But there are two advantages: first, the Win32 API does not try to “guess” the daylight savings at that time (they might be incorrect anyway) and second, the difference between two file timestamps is always the same regardless of the daylight savings. So you won’t reach the weird behavior when a file X is updated after file Y, but after entering in the DST interval X appears as being updated earlier than updating Y.

So, going back to the original question: how to fix this method? Simple. Instead of:

DateTime dtLocal = DateTime.FromFileTime(fileTime);

you write:

DateTime dtUTC = DateTime.FromFileTimeUtc(fileTime);
DateTime dtLocal = dtUTC + TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);

This ensures an equivalent behavior with FileTimeToLocalFileTime.  


P.S. Daylight time savings is a fascinating topic. There are several anecdotes here:

Draft Status, Vietnam War

A man, born just after 12 midnight, DST, circumvented the Vietnam War draft by using a daylight saving time loophole. When drafted, he argued that standard time, not DST, was the official time for recording births in his state of Delaware in the year of his birth. Thus, under official standard time he was actually born on the previous day—and that day had a much higher draft lottery number and allowed him to avoid the draft.

Palestinian Terrorists

In September 1999, the Palestinian West Bank was on daylight saving time while Israel had just switched back to standard time. West Bank Palestinians prepared time bombs and smuggled them to Arab Israelis, who misunderstood the time on the bombs. As the bombs were being planted, they exploded—one hour too early—killing three terrorists instead of two busloads of people, the intended victims.

[update: fixing typos]

Comments (3)

  1. psnarula says:

    this is unrelated to your comments about daylight saving time, but the post reminded me of a huge annoyance in windows — the inability to view the calendar in the system tray when i don’t have administrator privileges on the box. windows is so concerned about me altering the system time that it won’t even let me see what day of the week it is.

    and yes, i am aware that this can be fixed by using outlook or by having the admins give me the necessary permissions as described here:

    but is this really necessary? i feel like this should be a like a "read-only" file — let me view the date and time and let me make whatever changes i want but give me an "access denied" error if i try to save changes.

  2. AdiOltean says:

    I see. I think that unfortunately the calendar control was designed around the scenario to set the current date/time (not to get it).