Skip to main content
Home/Tools/Developer/Windows FILETIME Converter

Windows FILETIME Converter

Convert 64-bit Windows FILETIME and Active Directory timestamps to human-readable dates and back, with support for hex, decimal, and LDAP formats.

100% Private - Runs Entirely in Your Browser
No data is sent to any server. All processing happens locally on your device.

Convert Windows FILETIME values to readable dates — and back again

You are looking at an Active Directory export, a registry dump or an event log, and one of the columns holds a number like 133485408000000000. It is not a Unix timestamp, it is not milliseconds, and pasting it into an ordinary epoch converter gives you a date somewhere in the year 4 billion. That number is a Windows FILETIME, and this tool turns it into a date you can act on.

Paste the value, pick a timezone, and the converted date appears immediately — no button to press. The whole conversion runs in your browser using JavaScript BigInt arithmetic, so nothing you paste leaves the machine. That matters here more than it does for most converters, because FILETIME values usually arrive attached to real account names out of a directory you are not supposed to be pasting into a random web form.

What a FILETIME actually is

A FILETIME is a 64-bit integer counting 100-nanosecond intervals since 1 January 1601, 00:00:00 UTC. Two things about that definition explain almost every problem people have with it:

  • The unit is tiny. There are 10,000,000 of these intervals in a single second, which is why any FILETIME from the modern era is an 18-digit number. The size is not an error or a corrupted field.
  • The epoch is 1601, not 1970. Microsoft chose 1601 because it is the start of the first 400-year cycle of the Gregorian calendar that precedes the practical range of Windows dates. Everything else in computing counts from 1970, so a FILETIME is offset from a Unix timestamp by a fixed constant.

That constant is 11644473600 seconds — the number of seconds between 1601-01-01 and 1970-01-01. It is worth memorising if you work with Windows data, because the two conversion formulas are built entirely out of it and the factor of ten million:

DirectionFormula
FILETIME → Unix seconds(filetime / 10000000) - 11644473600
Unix seconds → FILETIME(unix + 11644473600) * 10000000

A worked conversion, both ways

Take the value at the top of this page, 133485408000000000:

  • Divide by 10,000,000: 133485408000000000 / 10000000 = 13348540800 seconds since 1601.
  • Subtract the epoch offset: 13348540800 - 11644473600 = 1704067200 seconds since 1970.
  • 1704067200 is 1 January 2024, 00:00:00 UTC.

Now run it backwards from a date. For 15 January 2025 at 12:30:45 UTC, the Unix timestamp is 1736944245:

  • Add the offset: 1736944245 + 11644473600 = 13381417845.
  • Multiply by 10,000,000: 133814178450000000.
  • In hexadecimal, the form you will see in a registry editor or an LDAP dump, that is 0x1DB67494C6C4880.

The tool accepts either notation on input. A value beginning 0x is treated as hexadecimal automatically, and both representations of whatever you paste are shown side by side in the results, so you can copy whichever one the next system wants.

The special values: 0 and 0x7FFFFFFFFFFFFFFF

Two FILETIME values are not timestamps at all, and Active Directory uses both heavily. If you convert them arithmetically you get nonsense — the year 1601 and the year 30828 respectively — so the tool intercepts them and tells you what they mean instead of producing a date.

ValueHexMeaning
00x0Never / not set. The attribute has no value yet.
92233720368547758070x7FFFFFFFFFFFFFFFNever expires. The maximum signed 64-bit integer, used as a sentinel.

The distinction bites hardest on accountExpires, where both values mean “this account never expires”. Which one you see depends on how the account was created: the AD Users and Computers console writes 0 when you tick “Never”, while accounts provisioned through some scripts and migrations carry the max-int sentinel. Any report that filters on accountExpires = 0 alone will quietly miss half the never-expiring accounts in the domain. Check for both.

On lastLogon and pwdLastSet, a zero is more interesting than it looks. pwdLastSet = 0 is the flag that forces a password change at next logon. A lastLogon of zero does not mean the account has never been used — it means it has never been used on the domain controller you queried, which is a very different claim.

Where you will run into FILETIME

The format is not confined to Active Directory, but AD is where most people meet it. These attributes all store FILETIME:

AttributeWhat it records
lastLogonLast interactive logon, held per domain controller and never replicated
lastLogonTimestampReplicated logon time, updated lazily — roughly every 14 days
pwdLastSetWhen the password was last changed
accountExpiresAccount expiry, or a “never” sentinel
badPasswordTimeLast failed authentication attempt
lockoutTimeWhen the account was locked out

Outside the directory, FILETIME turns up in NTFS file timestamps, in registry values such as USB device connection history and software install dates, in the SystemTime and TimeCreated fields of EVTX event records, and across the forensic artefacts built on top of them — prefetch files, LNK shortcuts, jump lists and shellbags. If you are triaging a host and a timestamp field is an unexplained 18-digit integer, FILETIME is the first thing to try.

The stale-account audit is the single most common reason people land here. Pull lastLogonTimestamp for every user, convert the column, and anything older than your threshold is a candidate for disabling — with the caveat that the attribute is deliberately imprecise. It only replicates after a lag, so a date up to a fortnight behind reality is expected behaviour, not a bug. For anything that needs to be accurate to the hour you have to query lastLogon on every domain controller and take the latest, because no single DC holds the whole picture.

Converting a whole column at once

Auditing rarely involves one timestamp. Switch to batch mode, paste one FILETIME per line straight out of your CSV or PowerShell output, and every row is converted into a table you can read down. Special values are labelled in place rather than silently producing a 1601 date, and unparseable lines are flagged individually instead of failing the whole batch — so a stray header row or a blank cell does not cost you the run.

The timezone selector applies to the whole conversion. UTC is the right default for incident timelines and anything you intend to correlate with logs from another system; switch to your local zone only when you are about to talk to a human about when something happened. The tool also detects your browser timezone on load and shows both the UTC and local renderings of every result, along with a relative age (“3 months ago”), which is usually the fastest way to eyeball whether an account is stale.

Doing it yourself, in the shell

For one-off checks you do not need a converter at all. PowerShell ships the conversion built in:

  • [DateTime]::FromFileTimeUtc(133485408000000000) gives you the UTC date; FromFileTime gives local time.
  • Going the other way, (Get-Date).ToFileTimeUtc() produces the current FILETIME.
  • Reading it straight off an account: Get-ADUser jsmith -Properties lastLogon | Select @{n='LastLogon';e={[DateTime]::FromFileTime($_.lastLogon)}}.

In Python there is no built-in, so you apply the formula: datetime(1601,1,1) + timedelta(microseconds=filetime//10), dividing by 10 because a microsecond is ten 100-nanosecond ticks. In .NET, DateTime.FromFileTimeUtc and DateTime.ToFileTimeUtc are the pair. The tool shows equivalent snippets for PowerShell, Python, C# and JavaScript on the page.

Precision, range and other honest limits

FILETIME carries 100-nanosecond resolution, but almost nothing populates it that finely. The Windows system clock is typically updated on a timer tick of around 15.6 milliseconds, so the trailing digits of a real-world FILETIME are usually zeros or noise rather than meaningful precision. This converter divides down to whole seconds before formatting, which means the sub-second remainder is not shown. For account auditing and event correlation that is irrelevant; if you are doing sub-second forensic sequencing, work with the raw integer and compare the values directly rather than the rendered dates.

On range: the arithmetic is done with BigInt, so there is no 53-bit floating point rounding of the kind that silently corrupts large timestamps in naive JavaScript implementations. Values that resolve outside the year 1–9999 window are rejected with an explicit error rather than being rendered as a plausible-looking wrong date. The theoretical maximum of a signed 64-bit FILETIME lands in the year 30828, but you will only ever see that value as the “never expires” sentinel described above.

Byte order: the trap in registry dumps

At the API level a FILETIME is not a single integer — it is a struct of two 32-bit halves, dwLowDateTime and dwHighDateTime. On x86 and x64 those are stored little-endian, so a raw hex dump of an eight-byte FILETIME shows the bytes in reverse order from how you would write the number. A value that reads 00 C0 89 76 45 3C DA 01 in a binary editor is 0x01DA3C457689C000 as a number, which is the 1 January 2024 example above. If a hex FILETIME converts to something absurd — a date in the 1600s, or thousands of years out — reversing the byte order is the first thing to try. Tools that read the registry for you (reg query, PowerShell’s Get-ItemProperty) hand you the assembled number and this does not apply; raw hive parsing and hex editors are where it bites.

Questions people actually ask

  • Is my data uploaded anywhere? No. The parsing, the arithmetic and the formatting all happen in your browser. There is no server call in the conversion path, so the account names and timestamps in an AD export stay on your machine.
  • Why does the date come out in 1601? Because the value was zero, or close to it. That is the epoch itself, and it means “not set”, not “seventeenth century”.
  • Why is my converted date the year 4 billion? You put a FILETIME into a Unix-epoch converter. It read ten-million-ticks-per-second as one-per-second.
  • Can I link to a conversion? Yes — the value is mirrored into the URL, so a converted timestamp can be pasted into a ticket or a chat and it opens already converted for whoever clicks it.
  • Does daylight saving affect the number? Never. A FILETIME is always UTC. Only the rendering you choose is affected, which is exactly why UTC is the safe choice for anything you plan to correlate later.

If the timestamp you are holding turns out to be seconds or milliseconds since 1970 rather than a FILETIME — the giveaway is a 10- or 13-digit number rather than an 18-digit one — our Unix timestamp converter handles that format instead.

Convert Windows FILETIME values to readable dates — and back again

You are looking at an Active Directory export, a registry dump or an event log, and one of the columns holds a number like 133485408000000000. It is not a Unix timestamp, it is not milliseconds, and pasting it into an ordinary epoch converter gives you a date somewhere in the year 4 billion. That number is a Windows FILETIME, and this tool turns it into a date you can act on.

Paste the value, pick a timezone, and the converted date appears immediately — no button to press. The whole conversion runs in your browser using JavaScript BigInt arithmetic, so nothing you paste leaves the machine. That matters here more than it does for most converters, because FILETIME values usually arrive attached to real account names out of a directory you are not supposed to be pasting into a random web form.

What a FILETIME actually is

A FILETIME is a 64-bit integer counting 100-nanosecond intervals since 1 January 1601, 00:00:00 UTC. Two things about that definition explain almost every problem people have with it:

  • The unit is tiny. There are 10,000,000 of these intervals in a single second, which is why any FILETIME from the modern era is an 18-digit number. The size is not an error or a corrupted field.
  • The epoch is 1601, not 1970. Microsoft chose 1601 because it is the start of the first 400-year cycle of the Gregorian calendar that precedes the practical range of Windows dates. Everything else in computing counts from 1970, so a FILETIME is offset from a Unix timestamp by a fixed constant.

That constant is 11644473600 seconds — the number of seconds between 1601-01-01 and 1970-01-01. It is worth memorising if you work with Windows data, because the two conversion formulas are built entirely out of it and the factor of ten million:

DirectionFormula
FILETIME → Unix seconds (filetime / 10000000) - 11644473600
Unix seconds → FILETIME (unix + 11644473600) * 10000000

A worked conversion, both ways

Take the value at the top of this page, 133485408000000000:

  • Divide by 10,000,000: 133485408000000000 / 10000000 = 13348540800 seconds since 1601.
  • Subtract the epoch offset: 13348540800 - 11644473600 = 1704067200 seconds since 1970.
  • 1704067200 is 1 January 2024, 00:00:00 UTC.

Now run it backwards from a date. For 15 January 2025 at 12:30:45 UTC, the Unix timestamp is 1736944245:

  • Add the offset: 1736944245 + 11644473600 = 13381417845.
  • Multiply by 10,000,000: 133814178450000000.
  • In hexadecimal, the form you will see in a registry editor or an LDAP dump, that is 0x1DB67494C6C4880.

The tool accepts either notation on input. A value beginning 0x is treated as hexadecimal automatically, and both representations of whatever you paste are shown side by side in the results, so you can copy whichever one the next system wants.

The special values: 0 and 0x7FFFFFFFFFFFFFFF

Two FILETIME values are not timestamps at all, and Active Directory uses both heavily. If you convert them arithmetically you get nonsense — the year 1601 and the year 30828 respectively — so the tool intercepts them and tells you what they mean instead of producing a date.

ValueHexMeaning
0 0x0 Never / not set. The attribute has no value yet.
9223372036854775807 0x7FFFFFFFFFFFFFFF Never expires. The maximum signed 64-bit integer, used as a sentinel.

The distinction bites hardest on accountExpires, where both values mean “this account never expires”. Which one you see depends on how the account was created: the AD Users and Computers console writes 0 when you tick “Never”, while accounts provisioned through some scripts and migrations carry the max-int sentinel. Any report that filters on accountExpires = 0 alone will quietly miss half the never-expiring accounts in the domain. Check for both.

On lastLogon and pwdLastSet, a zero is more interesting than it looks. pwdLastSet = 0 is the flag that forces a password change at next logon. A lastLogon of zero does not mean the account has never been used — it means it has never been used on the domain controller you queried, which is a very different claim.

Where you will run into FILETIME

The format is not confined to Active Directory, but AD is where most people meet it. These attributes all store FILETIME:

AttributeWhat it records
lastLogonLast interactive logon, held per domain controller and never replicated
lastLogonTimestampReplicated logon time, updated lazily — roughly every 14 days
pwdLastSetWhen the password was last changed
accountExpiresAccount expiry, or a “never” sentinel
badPasswordTimeLast failed authentication attempt
lockoutTimeWhen the account was locked out

Outside the directory, FILETIME turns up in NTFS file timestamps, in registry values such as USB device connection history and software install dates, in the SystemTime and TimeCreated fields of EVTX event records, and across the forensic artefacts built on top of them — prefetch files, LNK shortcuts, jump lists and shellbags. If you are triaging a host and a timestamp field is an unexplained 18-digit integer, FILETIME is the first thing to try.

The stale-account audit is the single most common reason people land here. Pull lastLogonTimestamp for every user, convert the column, and anything older than your threshold is a candidate for disabling — with the caveat that the attribute is deliberately imprecise. It only replicates after a lag, so a date up to a fortnight behind reality is expected behaviour, not a bug. For anything that needs to be accurate to the hour you have to query lastLogon on every domain controller and take the latest, because no single DC holds the whole picture.

Converting a whole column at once

Auditing rarely involves one timestamp. Switch to batch mode, paste one FILETIME per line straight out of your CSV or PowerShell output, and every row is converted into a table you can read down. Special values are labelled in place rather than silently producing a 1601 date, and unparseable lines are flagged individually instead of failing the whole batch — so a stray header row or a blank cell does not cost you the run.

The timezone selector applies to the whole conversion. UTC is the right default for incident timelines and anything you intend to correlate with logs from another system; switch to your local zone only when you are about to talk to a human about when something happened. The tool also detects your browser timezone on load and shows both the UTC and local renderings of every result, along with a relative age (“3 months ago”), which is usually the fastest way to eyeball whether an account is stale.

Doing it yourself, in the shell

For one-off checks you do not need a converter at all. PowerShell ships the conversion built in:

  • [DateTime]::FromFileTimeUtc(133485408000000000) gives you the UTC date; FromFileTime gives local time.
  • Going the other way, (Get-Date).ToFileTimeUtc() produces the current FILETIME.
  • Reading it straight off an account: Get-ADUser jsmith -Properties lastLogon | Select @{n='LastLogon';e={[DateTime]::FromFileTime($_.lastLogon)}}.

In Python there is no built-in, so you apply the formula: datetime(1601,1,1) + timedelta(microseconds=filetime//10), dividing by 10 because a microsecond is ten 100-nanosecond ticks. In .NET, DateTime.FromFileTimeUtc and DateTime.ToFileTimeUtc are the pair. The tool shows equivalent snippets for PowerShell, Python, C# and JavaScript on the page.

Precision, range and other honest limits

FILETIME carries 100-nanosecond resolution, but almost nothing populates it that finely. The Windows system clock is typically updated on a timer tick of around 15.6 milliseconds, so the trailing digits of a real-world FILETIME are usually zeros or noise rather than meaningful precision. This converter divides down to whole seconds before formatting, which means the sub-second remainder is not shown. For account auditing and event correlation that is irrelevant; if you are doing sub-second forensic sequencing, work with the raw integer and compare the values directly rather than the rendered dates.

On range: the arithmetic is done with BigInt, so there is no 53-bit floating point rounding of the kind that silently corrupts large timestamps in naive JavaScript implementations. Values that resolve outside the year 1–9999 window are rejected with an explicit error rather than being rendered as a plausible-looking wrong date. The theoretical maximum of a signed 64-bit FILETIME lands in the year 30828, but you will only ever see that value as the “never expires” sentinel described above.

Byte order: the trap in registry dumps

At the API level a FILETIME is not a single integer — it is a struct of two 32-bit halves, dwLowDateTime and dwHighDateTime. On x86 and x64 those are stored little-endian, so a raw hex dump of an eight-byte FILETIME shows the bytes in reverse order from how you would write the number. A value that reads 00 C0 89 76 45 3C DA 01 in a binary editor is 0x01DA3C457689C000 as a number, which is the 1 January 2024 example above. If a hex FILETIME converts to something absurd — a date in the 1600s, or thousands of years out — reversing the byte order is the first thing to try. Tools that read the registry for you (reg query, PowerShell’s Get-ItemProperty) hand you the assembled number and this does not apply; raw hive parsing and hex editors are where it bites.

Questions people actually ask

  • Is my data uploaded anywhere? No. The parsing, the arithmetic and the formatting all happen in your browser. There is no server call in the conversion path, so the account names and timestamps in an AD export stay on your machine.
  • Why does the date come out in 1601? Because the value was zero, or close to it. That is the epoch itself, and it means “not set”, not “seventeenth century”.
  • Why is my converted date the year 4 billion? You put a FILETIME into a Unix-epoch converter. It read ten-million-ticks-per-second as one-per-second.
  • Can I link to a conversion? Yes — the value is mirrored into the URL, so a converted timestamp can be pasted into a ticket or a chat and it opens already converted for whoever clicks it.
  • Does daylight saving affect the number? Never. A FILETIME is always UTC. Only the rendering you choose is affected, which is exactly why UTC is the safe choice for anything you plan to correlate later.

If the timestamp you are holding turns out to be seconds or milliseconds since 1970 rather than a FILETIME — the giveaway is a 10- or 13-digit number rather than an 18-digit one — our Unix timestamp converter handles that format instead.

Loading interactive tool...

You build the idea. I'll ship the product.

Productized MVP development for founders. 9 SaaS apps shipped — yours could be next, in 6 weeks. Secure by default.

ℹ️ Disclaimer

This tool is provided for informational and educational purposes only. All processing happens entirely in your browser - no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results. Use at your own discretion.