Aaron
Aaron

Reputation: 4480

DateTime ToFileTime and ToFileTimeUtc have same output

I opened a file and used ToUniversalTime() and ToLocalTime() and output different times. However, when I use ToFileTime() and ToFileTimeUtc(), I get the same number. Why is this?

DateTime creationTime = File.GetCreationTime(@"c:\windows\setupact.log");
Console.WriteLine("utc time: " + creationTime.ToUniversalTime());
Console.WriteLine("file time: " + creationTime.ToLocalTime());
Console.WriteLine("file: " + creationTime.ToFileTime());
Console.WriteLine("utc: " + creationTime.ToFileTimeUtc());

output

utc time: 8/22/2013 2:46:17 PM

file time: 8/22/2013 7:46:17 AM

file: 130216563774628355

utc: 130216563774628355

Shouldn't file and utc be different?

Upvotes: 8

Views: 13524

Answers (3)

mklement0
mklement0

Reputation: 438468

There's good information in the existing answers, but let me attempt a pragmatic summary:

The only time the distinction between System.DateTime.ToFileTime() and System.DateTime.ToFileTimeUtc() matters is when the instance's .Kind property equals Unspecified, i.e., if it's unclear whether the time value represents a local or UTC time.
This information was actually in an answer by Hans Passant that he himself deleted.

In other word: for System.DateTime instances whose .Kind property equals either Local or Utc (the only other possible values), System.DateTime.ToFileTime() and System.DateTime.ToFileTimeUtc() behave identically - this is what the OP experienced, because his input value was of .Kind Local (the kind returned by File.GetCreationTime()).

Note that the related System.DateTimeOffset type by design always carries explicit UTC offset information, so there's never ambiguity, which is probably why that type has only a .ToFileTime() method (and not also .ToFileTimeUtc()).

As others have noted, the return value always represents a UTC time:

  • File time values by definition, invariably represent a point in time in UTC.

  • Thus, both .ToFileTime() and .ToFileTimeUtc() create a point in time expressed as the count of 100ns intervals since midnight January 1, 1601 UTC.

To complement the OP's own example with one where .ToFileTime() and .ToFileTimeUtc() do differ in outcome:

// Create a DateTime instance with .Kind equal to Unspecified;
// use the earliest date that can be represented as a file time.
DateTime dtUnspecified = DateTime.Parse("1601-01-01");

Console.WriteLine(
    dtUnspecified.ToFileTime() + "\n" +
    dtUnspecified.ToFileTimeUtc()
);

Sample output in the US Eastern time zone:

180000000000  // 1601-01-01T05:00:00Z - 5 AM UTC
0             // 1601-01-01T00:00:00Z - midnight UTC

Upvotes: 7

albertjan
albertjan

Reputation: 7817

From the docs:

A Windows file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC). Windows uses a file time to record when an application creates, accesses, or writes to a file.

The number of nanoseconds since 1-1-1601 UTC, don't change no matter in which timezone you are.

From the source of the .net framwork:

public long ToFileTime() {
    // Treats the input as local if it is not specified
    return ToUniversalTime().ToFileTimeUtc();
}

public long ToFileTimeUtc() {
    // Treats the input as universal if it is not specified
    long ticks = ((InternalKind & LocalMask) != 0) ? ToUniversalTime().InternalTicks : this.InternalTicks;
    ticks -= FileTimeOffset;
    if (ticks < 0) {
        throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid"));
    }
    return ticks;
}

So when you use ToFileTimeUtc and you have an unspecified DateTime it gives you the nanosecs since 1-1-1601, no matter what timezone it's originally from. Which could for an hour each year if the timezone has DST give you an invalid time.

Upvotes: 2

Cameron
Cameron

Reputation: 2594

If you look at the ToFileTime() documentation on MSDN, it says:

A Windows file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC). Windows uses a file time to record when an application creates, accesses, or writes to a file.

All file times are stored in UTC. Then applications such as Explorer convert the UTC time to Local Time for display purposes.

If you look further into the remarks section of ToFileTime(), you will see a "Notes to Callers" section. That further explains how ToFileTime() and ToFileTimeUtc() were expected to be used.

Upvotes: 0

Related Questions