The Active Directory Integer8 data type is used to represent dates. Integer8 values are 64-bit (8-byte) integers that represent dates as the number of 100-nanosecond intervals since 12:00 AM January 1, 1601. In PowerShell, these 100-nanosecond intervals are called ticks. PowerShell represents dates as the number of ticks since 12:00 AM January 1, 0001. Remember, there was no year 0000. The previous day was December 31, 0001 BC. Leap seconds are not accounted for. In addition, the switch from the Julian to Gregorian calendars in 1582, when October 4, 1582, was followed by October 15, is ignored.

The following table shows the number of ticks equivalent to several dates.

Date (UTC) PowerShell Ticks AD Ticks
January 1, 0001, 00:00:00 0 N/A
January 1, 1601, 00:00:00 504,911,232,000,000,000 0
March 21, 2011, 00:00:00 634,362,624,000,000,000 129,451,392,000,000,000
December 31, 9999, 23:59:59.9999999 3,155,378,975,999,999,999 2,650,467,743,999,999,999
September 14, 30828, 02:48:05.478 N/A 9,223,372,036,854,775,807

The difference between the number of PowerShell (or .NET Framework) ticks and the number of Active Directory Integer8 ticks corresponding to any particular date is the number of ticks in 1600 years. This is 1600 * 365.2425 * 24 * 60 * 60 * 10000000 = 504,911,232,000,000,000 ticks.

Why make note if this? Well, first, we sometimes need to convert between PowerShell and Active Directory dates. This is easily done by adding or subtracting the equivalent of 1600 years. However, it is also possible for the Active Directory accountExpires attribute to have the maximum value possible for a 64-bit number, which is 2^63 -1, or 9,223,372,036,854,775,807. If an Active Directory account has never had an expiration date, this is the value assigned to the accountExpires attribute. It really means "never". However, the .NET Framework defines a maximum value for the ticks in a DateTime value, which is the number of ticks in the date December 31, 9999, 23:59:59.9999999. If a PowerShell script attempts to convert the integer 2^63 -1 into a date, an error is raised. The script must test for this condition and assign a value equivalent to "never" before attempting to convert into a DateTime value. The following PowerShell script demonstrates how to retrieve the account expiration date for a specified Active Directory user. This can be used in PowerShell V1 or V2:

$User = [ADSI]"LDAP://CN=Jim Smith,ou=West,dc=MyDomain,dc=com"

$AcctExp = $User.accountExpires.Value
$lngValue = $User.ConvertLargeIntegerToInt64($AcctExp)

# A value of 0 or 2^63-1 means never.
If ($lngValue -gt [DateTime]::MaxValue.Ticks)
{
    $lngValue = 0
}
# Convert 64-bit integer into DateTime.
$Date = [DateTime]$lngValue
If ($Date -eq 0)
{
    $AcctExpires = "<Never>"
}
Else
{
    # Convert Active Directory ticks to PowerShell ticks.
    # Also convert from UTC to local time.
    $AcctExpires = $Date.AddYears(1600).ToLocalTime()
}
$AcctExpires

The expression [DateTime]::MaxValue in the code above is the maximum date in the .NET Framework, December 31, 9999, 23:59:59.9999999. The expression [DateTime]::MaxValue.Ticks is the equivalent in PowerShell ticks, or 3,155,378,975,999,999,999. A similar script using the Active Directory module Get-ADUser would be as follows. This requires PowerShell V2:

$User = Get-ADUser -Identity jsmith -Properties accountExpires

$lngValue = $User.accountExpires
If (($lngValue -eq 0) -or ($lngValue -gt [DateTime]::MaxValue.Ticks))
{
    $AcctExpires = "<Never>"
}
Else
{
    $Date = [DateTime]$lngValue
    $AcctExpires = $Date.AddYears(1600).ToLocalTime()
}
$AcctExpires