Active Directory and LDAP store timestamps as 100-nanosecond intervals since January 1, 1601 (UTC). This converter handles both directions: paste an LDAP timestamp to get a date, or paste a date to get the LDAP value.
Microsoft Active Directory and LDAP-based systems use a 64-bit integer to represent time. The value counts 100-nanosecond intervals elapsed since 1601-01-01 00:00:00 UTC. This is the same format used by Windows FILETIME.
You'll typically encounter it in attributes like lastLogon, pwdLastSet, accountExpires, and lastLogonTimestamp. The values look like enormous integers — typically 18 digits long.
unix_seconds = (ldap_value / 10_000_000) - 11_644_473_600
Divide by 10 million to get from 100ns intervals to seconds, then subtract the offset between 1601-01-01 and 1970-01-01.
ldap_value = (unix_seconds + 11_644_473_600) * 10_000_000
0 — the user never logged on (for lastLogon), or the password never expires (for some uses).9223372036854775807 (max Int64) — represents "never" for accountExpires.9223372036854775806 — also represents "never" in some contexts.# Convert LDAP timestamp to date
[DateTime]::FromFileTimeUtc(133829280000000000)
# → Wednesday, January 1, 2025 12:00:00 AM
# Convert date to LDAP timestamp
([DateTime]"2025-01-01 00:00:00").ToFileTimeUtc()
from datetime import datetime, timezone
LDAP_EPOCH_DELTA = 11_644_473_600 # seconds between 1601 and 1970
def ldap_to_datetime(ldap_value: int) -> datetime:
unix_seconds = (ldap_value / 10_000_000) - LDAP_EPOCH_DELTA
return datetime.fromtimestamp(unix_seconds, tz=timezone.utc)
def datetime_to_ldap(dt: datetime) -> int:
return int((dt.timestamp() + LDAP_EPOCH_DELTA) * 10_000_000)
const LDAP_OFFSET_SEC = 11644473600;
function ldapToDate(ldap) {
const sec = (ldap / 10_000_000) - LDAP_OFFSET_SEC;
return new Date(sec * 1000);
}
function dateToLdap(date) {
return (Math.floor(date.getTime() / 1000) + LDAP_OFFSET_SEC) * 10_000_000;
}