Common FileTime Pitfalls for Developers and How to Fix Them

FileTime vs. Unix Time: Key Differences and Conversion Methods

What each format is

  • FileTime (Windows FILETIME): 64-bit integer counting 100-nanosecond intervals since 00:00:00 UTC on January 1, 1601 (Gregorian). Used by NTFS, Win32 APIs, and Windows runtimes.
  • Unix Time (POSIX/time_t): integer (commonly 32‑ or 64‑bit) counting seconds since 00:00:00 UTC on January 1, 1970. Widely used on Unix-like systems and in many programming languages.

Key differences

  • Epochs: FileTime epoch = 1601-01-01; Unix epoch = 1970-01-01.
  • Resolution: FileTime = 100 ns (10^-7 s) ticks; Unix time = 1 s (though many modern APIs support subsecond precision as float or separate fields).
  • Range: FILETIME’s 64-bit ticks cover far wider date range than 32-bit Unix time (which overflows in 2038). 64-bit time_t avoids that overflow.
  • Typical storage/representation: FileTime uses two 32-bit fields (dwLowDateTime, dwHighDateTime) or a 64-bit integer; Unix time commonly a single signed integer/64-bit integer or a floating-point seconds value for fractions.
  • Time zone: Both measure absolute UTC instants; localized display requires conversion to local time separately.

Conversion basics (math)

  • Ticks per second = 10,000,000 (because each tick = 100 ns).
  • Offset between epochs (in FILETIME ticks) = 116444736000000000. This equals the number of 100‑ns intervals from 1601-01-01 to 1970-01-01.

Formulas:

  • FILETIME (ticks) -> Unix seconds: unix_seconds = (filetime_ticks – 116444736000000000) / 10_000_000
  • Unix seconds -> FILETIME ticks: filetime_ticks = unix_seconds10_000_000 + 116444736000000000
  • For subsecond precision using milliseconds or nanoseconds, multiply/divide accordingly (e.g., multiply unix seconds by 1_000 to get milliseconds, by 1_000_000000 for nanoseconds).

Example conversions (code snippets)

C/C++ (Win32 style, using 64-bit integer)

c

// FILETIME -> unix time (seconds) int64_t filetime_to_unix(uint64_t ft) { const uint64_t EPOCH_DIFF = 116444736000000000ULL; return (int64_t)((ft - EPOCH_DIFF) / 10000000ULL); } // unix time (seconds) -> FILETIME uint64_t unix_to_filetime(int64_t unix_sec) { const uint64_t EPOCH_DIFF = 116444736000000000ULL; return (uint64_t)unix_sec 10000000ULL + EPOCHDIFF; }

C# (.NET)

csharp

// From FileTime (long) to DateTime DateTime dt = DateTime.FromFileTimeUtc(filetimeLong); // From DateTime or Unix seconds to FileTime long ft = dt.ToFileTimeUtc(); // or from unix seconds: long ft2 = unixSeconds 10_000000L + 116444736000000000L;

PowerShell

powershell

# FILETIME -> DateTime [datetime]::FromFileTimeUtc(130927962789982434) # Unix seconds -> DateTime [datetime]::UnixEpoch.AddSeconds(1610000000)

Python

python

# FILETIME ticks -> unix seconds EPOCH_DIFF = 116444736000000000 unix = (filetime_ticks - EPOCH_DIFF) / 10_000_000 # unix seconds -> FILETIME filetime = int(unix_seconds * 10_000_000) + EPOCH_DIFF

Practical tips and pitfalls

  • Always treat both values as UTC instants; convert to local time only for display.
  • Beware of signed/unsigned types and overflow when using 32-bit integers. Use 64-bit integers for FILETIME math.
  • When converting FILETIME stored as two 32-bit parts, combine low/high into a 64-bit value: ticks = ((uint64_t)high << 32) | low.
  • For high-precision timestamps (subsecond), keep fractional seconds explicitly (milliseconds, microseconds, or 100‑ns ticks) instead of truncating to whole seconds.
  • FAT filesystem and some Windows APIs may store or return local times—use documented API helpers (FileTimeToSystemTime, FileTimeToLocalFileTime) when appropriate.

Quick reference table

Concept FileTime Unix Time
Epoch 1601-01-01 UTC 1970-01-01 UTC
Unit 100 ns ticks 1 second (commonly)
Typical type 64-bit integer / FILETIME struct 64-bit integer or float
Conversion constant 116444736000000000 ticks offset same (used in formulas)
Common API helpers GetFileTime, FileTimeToSystemTime time(), gmtime(), localtime()

When to use which

  • Use FileTime when interacting with Windows system calls, NTFS metadata, or Win32/COM APIs.
  • Use Unix time for POSIX systems, inter-process simple numeric timestamps, or cross-platform APIs that expect seconds since 1970. Convert at the boundary between systems.

If you want, I can add a ready-to-copy utility function in the language you use (Go, Rust, Java, JavaScript, etc.).

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *