'Exporting/Importing dates from Active Directory

Simple export script to grab users from Active Directory and output a .csv file:

$ad_users = Get-ADUser -SearchBase $adPath -LDAPFilter $filter -Properties samAccountName, DisplayName, LastLogonDate, accountExpires |

export-csv -Path $exportPath -nti

For the account expiration, users sometimes will have 0 or 9223372036854770000. I know in both situations it means the account is set to never expire, but why the difference? Why two different values to represent the same thing?

And then in the case of the last logon date, I get an actual date string like "10/12/2022 8:42:56 AM".

Why the inconsistencies? One is a date string the other a timestamp (who stores time in nanoseconds from 1600 anyway)?

Currently, how I'm converting the timestamp:

$account_expire = ([DateTime]$expires_timestamp).AddYears(1600).ToLocalTime()


Solution 1:[1]

• According to your question regarding the ‘Account expires’ and ‘Account expiration date’ attributes wherein ‘account expires’ can be called in AD powershell cmdlets while the ‘account expiration date’ is an attribute for everyone in AD which can be seen in ADSI console. The data that is stored regarding the date when a user account expires on the "Account" tab of the user properties dialog is stored in the ‘accountExpires’ attribute of the user object in Active directory and can be accessed and viewed from the ‘adsiedit.msc’ interface. While the property called ‘AccountExpirationDate’ is exposed by the IADs User interface, it can be used to display and set this date.

• Thus, if you compare ‘accountExpires’ attribute and ‘AccountExpirationDate’, it is common for the values to differ by a day, sometimes even two days. The ‘accountExpires’ attribute of the user object is data type ‘Integer’. Integer values are 64-bit (8-byte) numbers representing dates as the number of 100-nanosecond intervals (also called ticks) since 12:00 AM January 1, 1601. One 100-nanosecond interval is 0.0000001 seconds. It sounds like that should be a huge number, and that’s why it requires a 64-bit value. 12:00 AM January 1, 2006, works out to be 127,805,472,000,000,000 100-nanosecond intervals since 12:00 AM January 1, 1601.

• The ‘AccountExpirationDate’ property method is a holdover from NT domains, where if a user object in Active Directory has never had an expiration date, the ‘accountExpires’ attribute is set to a huge number. The actual value is ‘2^63 – 1, or 9,223,372,036,854,775,807’. This is because 64-bit numbers can range from ‘-2^63 to 2^63 – 1’, making this the largest number that can be saved as a 64-bit value. Obviously, this represents a date so far in the future that cannot be interpreted. In fact, ‘AccountExpirationDate’ raises an error if it attempts to read this value. If a user object has an expiration date, and then you remove this date in ADUC by selecting "Never" on the "Account" tab, the GUI sets ‘accountExpires’ to 0. Thus, the values 0 and 2^63 - 1 both really mean "Never".

• The only values that you can assign to the ‘accountExpires’ attribute in VBScript is 0 and -1. Because of the way 64-bit values are handled, -1 is actually 2^63 - 1, the huge number referred to above. The value 0 corresponds to the date/time 12:00 AM January 1, 1601. The value -1 corresponds to September 14 of the year 30,828. For more detailed information regarding the usage and concept of this attribute, kindly refer to the link below: -

https://www.rlmueller.net/AccountExpires.htm

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 KartikBhiwapurkar-MT