DateTime conversion

Recently a colleague of mine asked me why he could do this and couldn’t get the correct date?

(Get-ADUser $UserName -Properties LastLogon).LastLogon |
Get-Date

Well, some properties are stored as a 64bit integer in Active Directory:

Like many other properties found in Active Directory, these 64bit integers represent the number of 100-nanosecond intervals since January 1, 1601 (UTC)

Then why can’t I pipe a 64bit integer into the Get-Date cmdlet and get the correct date?
I can do the following, I can pipe a string and immediately get the correct date:

'31/12/2018' | Get-date

The Get-Date cmdlet will treat the input as a datetime object.
Both the help of the Get-Date cmdlet and its source code shows it.

Why the datetime object does not convert correctly the Active Directory 64bit integer?
The datetime object has many constructors.

[System.DateTime].GetConstructors().GetParameters() | 
Select -Unique | Select Name,Member

DateTime Constructor (Int64) documented on this page says it uses A date and time expressed in the number of 100-nanosecond intervals that have elapsed since January 1, 0001 at 00:00:00.000 in the Gregorian calendar.

Fortunately, there’s a another method documented that deals with ticks elapsed since 1/1/1601 and not 1/1/0001.
The DateTime.FromFileTime Method (Int64) documented on this page says:

A Windows file time expressed in ticks.
A Windows file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC). Windows uses a file time to record when an application creates, accesses, or writes to a file.

This means that I can get the correct date if I do:

[DateTime]::FromFileTime('131787092608430925')
# or
[DateTime]::FromFileTime(
(Get-ADUser $UserName -Properties LastLogon).LastLogon
)

Ok, there’s still some magic happening behind the scene. How do I know what the PowerShell engine does? When does it use a method or a constructor?
There’s an excellent post about this topic on the PowerShell Team blog:
Understanding PowerShell’s Type Conversion Magic

Trace-Command -Expression {  
 '31/12/2018' | Get-date
} -PSHost -Name TypeConversion

Trace-Command -Expression { 
 [int64]'131787092608430925' | Get-date
} -PSHost -Name TypeConversion

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.