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]