PowerShell Get-ADUser, output to JSON with formatted DateTime

Viewed 567

I'll say first that I'm not very experienced with PowerShell, so many things are not obvious to me.

I've got the following command:

$JSON = Get-ADUser -Filter "SAMAccountName -eq 'jdray'" -Properties SAMAccountName,
    Name,
    DisplayName,
    Manager,
    SAMAccountType,
    pwdLastSet,
    Created,
    AccountExpirationDate,
    lastLogonTimestamp,
    DistinguishedName|Select-object -Property SAMAccountName,
                                    Name,
                                    @{name='Manager';expression={ ([ADSI]"LDAP://$($_.manager)").displayname }},
                                    Enabled,
                                    DistinguishedName,
                                    Created,
                                    AccountExpirationDate,
                                    LastLogonTimestamp,
                                    PasswordLastSet|ConvertTo-Json

The output of this is:

{
    "SAMAccountName":  "jdray",
    "Name":  "Ray, James",
    "Manager":  "Lady, Boss",
    "Enabled":  true,
    "DistinguishedName":  "CN=Ray\\, James,OU=...[yadda yadda yadda]...DC=com",
    "Created":  "\/Date(1554387070000)\/",
    "AccountExpirationDate":  "\/Date(1643702400000)\/",
    "LastLogonTimestamp":  132732539928955494,
    "pwdLastSet":  132729945927805005
}

First of all, I'm confused why AccountExpirationDate and Created have one format, but LastLogonTimestamp and pwdLastSet are formatted differently.

What I really want is to have all the DateTime objects output in a human-readable DateTime format. I tried -ExpandProperty, but couldn't figure out how to make it work. It appears to add a property named DateTime to the end of the output, formatted reasonably: "DateTime": "Thursday, April 4, 2019 7:11:10 AM", but it doesn't name it. The Microsoft documentation on the subject is very light on useful examples, as is the rest of the web.

I tried following the @{} format for the Manager expression, which I copied from someone else's script. Unfortunately my PowerShell isn't strong enough to figure out a reasonable expression. In C#, something like Created.ToShortDateString() would suffice (presuming Created is a DateTime).

So, how do I consistently output named, human-readable DateTime property values in a JSON array?

EDIT

Using a proposed answer below, I modified the four timestamp fields using the same pattern:

@{n='Created';e={[DateTime]::FromFileTime($_.Created)}},
@{n='AccountExpirationDate';e={[DateTime]::FromFileTime($_.AccountExpirationDate)}},
@{n='LastLogonTimestamp';e={[DateTime]::FromFileTime($_.lastLogonTimestamp)}},
@{n='pwdLastSet';e={[DateTime]::FromFileTime($_.pwdLastSet)}}

Here's the (frustrating) result I got:

 "Created":  "\/Date(1554387070000)\/",
 "AccountExpirationDate":  "\/Date(1643702400000)\/",
 "LastLogon":  {
                   "value":  "\/Date(1628780392895)\/",
                   "DateTime":  "Thursday, August 12, 2021 7:59:52 AM"
               },
 "pwdLastSet":  132729945927805005

Also of note, here's the output for the four DateTime fields before it gets translated to JSON:

Created               : 4/4/2019 7:11:10 AM
AccountExpirationDate : 2/1/2022 12:00:00 AM
LastLogonTimestamp    : 8/12/2021 7:59:52 AM
PasswordLastSet       : 8/9/2021 7:56:32 AM

Why does that formatting work for one DateTime instance but not the rest?

How do I extract DateTime from the format of the pwdLastSet field, which is clearly a different animal?

How do I get a simple property:value pair, such as "LastLogonTimestamp": "Thursday, August 12, 2021 7:59:52 AM"?

1 Answers

Use DateTime.FromFileTime(LastLogonTimestamp) $JSON=Get-ADUser -Filter {Enabled -eq $true} -Properties Name,Manager,LastLogon | Select-Object Name,Manager,@{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}

Related