How to Use This Tool
Paste a FILETIME in decimal or hex and get a date, or go the other way. Everything is done with exact integer arithmetic.
What the number means
A FILETIME is a count of 100-nanosecond intervals — usually called ticks — since 1 January 1601 UTC. There are 10,000,000 ticks in a second and 864,000,000,000 in a day, which is why the values are so long.
Converting to Unix time is a single subtraction and a division:
unix_seconds = (filetime − 116444736000000000) ÷ 10000000
That constant is the 11,644,473,600 seconds between the two epochs, expressed in ticks. It is worth recognising on sight: a FILETIME equal to it is exactly the Unix epoch.
Why 1601
The Gregorian calendar repeats on a 400-year cycle, and 1601 begins the cycle that was current when the format was specified. Choosing the start of a cycle makes leap-year arithmetic uniform across the whole representable range, which matters when the range is thousands of years long.
It is not an arbitrary date, and it is also not a date anything was recorded on — a FILETIME near zero is almost always uninitialised memory rather than a seventeenth-century event.
Precision is the trap
A JavaScript number holds integers exactly only up to 253, which is 9,007,199,254,740,991. A
current FILETIME is around 1.33 × 1017 — about fourteen times larger — so
reading one with parseInt or Number() rounds it.
The failure is nasty because it is small. The date comes out looking entirely plausible and is wrong by some fraction of a second, or occasionally by more. Anything comparing two timestamps for equality, or sorting by them, will then behave strangely for reasons that do not show up in the output.
This page uses BigInt throughout, so the digits you paste are the digits used.
Where you meet these
- Active Directory stores
lastLogonTimestamp,pwdLastSetandaccountExpiresas FILETIME. These are the values most people are converting. - Registry exports and many Windows event log fields.
- NTFS file creation, modification and access times.
- Forensic tools, which frequently present raw ticks rather than a formatted date.
The sentinel values
Two values mean "not set" rather than a date, and converting them produces nonsense:
- 0 — never set. It converts to 1601-01-01, which is not a claim about anything.
- 9223372036854775807 (263−1) — the "never expires" marker on
accountExpires. It converts to a date around the year 30828 and means the account has no expiry.
A report that shows users whose accounts expired in 1601 has converted the first without checking. This page flags both.
The high and low pair
The underlying structure splits the value into two 32-bit halves, and some tools print them separately
as dwHighDateTime and dwLowDateTime. Recombining is
high × 232 + low, which the pair option above accepts directly — and
which is another place the arithmetic overflows an ordinary number.
