Modify date in description field from user account

In AD we disable users and we add to the description field

disabled by Paul on 2020-04-09 last workdate 2020-04-08

however there are people that disable an account and put in the dates like dd-mm-yyyy or mm-dd-yyyyy or yyyy-mm-dd

I would like to standardize this so that every description field gets disabled by Paul 2020-apr-09 last workdate 2020-apr-08

only I don’t know how to achieve this
basically this would mean that I read each description field into a variable change the date and put the corrected description back in the description field for the same user

example current situation is disabled by Paul on 2020-04-09 last workdate 2020-04-08
after running the script disabled by Paul on 2020-apr-09 last workdate 2020-apr-08

thanks for your help

Paul

If you give it a shot, post what you tried and then maybe we can help you get it going.

Hmmm … that’s nearly impossible to automate I’m afraid. How would you distinguish the 1st of February from the 2nd of January then? … or to stay with your example the 8th of April from the 4th of August?

I now have something like this

[pre]
$user = “samaccountname”
$texttobemod = (get-aduser -identity $user -properties description).Description
$content = Get-Content $texttobemod
$content =$content -replace ‘(19|20)\d\d- /.- /.’, [datetime]::Today.ToString(‘yyyy-MMM-dd’)

[/pre]
you got a point there Olaf, would working with select case do the trick? or would it still be impossible to determine?

 

I don’t understand this question.

When I present you a date lets say “01/12/2020”. Would you be able to tell if it’s the 1st of December or the 12th of January? There are more than 10 month in between … choose wisely. :wink: :smiley:

I mean of course there are a lot of dates you could determine exactly but if there is the possibilty of ambiguity you’d need a second attribute to support the choice you need to do.

Olaf,
you are absolutely right we are not able to determine the difference here.
I guess I have to leave the past behind and don’t care about the crappy data from the past.

unless we can get hold of the date in the users object tab and use the Modified date as reference?

That’s what I meant with “a second attribute”. :wink: It’ll make your code a lot more complex but if that’s what you need. :wink:

as mentioned previously I’m stuck with the code that I have what do I need to do to make it work?

Hmmmm … that’s gonna be a little more complex than you might think of, I’m afraid. :wink:
You told that there are different formattings possible, right? So you would need to determine first, what format you have. Therefor you need to get the month and the date string, maybe turn it into an integer and check whether it’s one of the ambiguous ones. If not you could replace it right away if not you’d need to process further.
Let’s say you have the 13th and the 14th of March in the description you could start with something like this:

$ExampleSourceStringList = @(
‘disabled by Paul on 2020-03-14 last workdate 2020-03-13’,
‘disabled by Paul on 03-14-2020 last workdate 03-13-2020’,
‘disabled by Paul on 14-03-2020 last workdate 13-03-2020’
)
foreach($ExampleSourceString in $ExampleSourceStringList){
Select-String -InputObject ExampleSourceString -Pattern '(?<=\s|-|)\d{2}-\d{2}(?=\s|-|$)’ -AllMatches |
Select-Object -ExpandProperty Matches |
Select-Object -ExpandProperty Value
}

There likely might be more sophisticated solutions but I don’t have a better idea at the moment.

I would just use the date-recognition capability already built into Get-Date, as in:

function FindAndFormat-DateTime {

# https://powershell.org/forums/topic/modify-date-in-description-field-from-user-account/

    [CmdletBinding(ConfirmImpact='Low')] 
    Param(
        [Parameter(Mandatory=$false)][String[]]$Description = 'disabled by Paul on 2020-04-09 last workdate 2020-04-08',
        [Parameter(Mandatory=$false)][String]$Delimiter = ' ',
        [Parameter(Mandatory=$false)][String]$DesiredDateFormat = 'yyyy-MMM-dd'
    )

    Begin { }

    Process {

        foreach ($InputString in $Description) {
            Write-Verbose "Processing string '$InputString'"
            $Result = foreach ($Word in ($InputString -split $Delimiter)) {
                try {
                    $IdentifiedDate = Get-Date $Word -Format $DesiredDateFormat -EA 1 
                    Write-Verbose "    Identified Date '$Word', reformatting as '$IdentifiedDate'"
                    $IdentifiedDate
                } catch {
                    $Word
                }
            } 
            $Result -join $Delimiter
        }

    } 

    End { }
}

Sample output:

FindAndFormat-DateTime -Description  @(
'disabled by Paul on 2020-03-14 last workdate 2020-03-13',
'disabled by Paul on 03-14-2020 last workdate 03-13-2020',
'disabled by Paul on 14-03-2020 last workdate 13-03-2020'
) -Verbose

VERBOSE: Processing string 'disabled by Paul on 2020-03-14 last workdate 2020-03-13'
VERBOSE:     Identified Date '2020-03-14', reformatting as '2020-Mar-14'
VERBOSE:     Identified Date '2020-03-13', reformatting as '2020-Mar-13'
disabled by Paul on 2020-Mar-14 last workdate 2020-Mar-13
VERBOSE: Processing string 'disabled by Paul on 03-14-2020 last workdate 03-13-2020'
VERBOSE:     Identified Date '03-14-2020', reformatting as '2020-Mar-14'
VERBOSE:     Identified Date '03-13-2020', reformatting as '2020-Mar-13'
disabled by Paul on 2020-Mar-14 last workdate 2020-Mar-13
VERBOSE: Processing string 'disabled by Paul on 14-03-2020 last workdate 13-03-2020'
disabled by Paul on 14-03-2020 last workdate 13-03-2020

This function will take one or more input strings, parse it by the $Delimiter, and examine each piece to see if it can be recognized as [DateTime]. If so, it will reformat it as $DesiredDateFormat. It will then reassemble and return the string.

@Sam Wow … great solution. 2 out of 3 on a German Windows as well. Probably the real world hit rate will be even higher.

Thank you very much

[quote quote=216906]@Sam Wow … great solution. 2 out of 3 on a German Windows as well. Probably the real world hit rate will be even higher.

Thank you very much[/quote]

Thanks Olaf :slight_smile:

@Sam @Olaf sweet thanks for your help

found it

 

Something like

FindAndFormat-DateTime -Description @(
(get-aduser -identity $user -properties description).Description
) -Verbose

Take a look at this:

Search-ADAccount –AccountDisabled –UsersOnly  |
    ForEach-Object {
        $User = Get-ADUser -Identity $_.sAMAccountName -Properties Description 
        $ChangedDescription = FindAndFormat-DateTime -Description $User.Description
        Set-ADUser -Identity $_.sAMAccountName -Description $ChangedDescription
    }

thanks guys
I started to experiment with your examples and came up with this

[pre]

function FindAndFormat-DateTime {

https://powershell.org/forums/topic/modify-date-in-description-field-from-user-account/

[CmdletBinding(ConfirmImpact=‘Low’)]
Param(

[Parameter(Mandatory=$false)][String[]]$Description = ‘disabled by Paul on 2020-04-09 last workdate 2020-04-08’,
[Parameter(Mandatory=$false)][String]$Delimiter = ’ ',
[Parameter(Mandatory=$false)][String]$DesiredDateFormat = ‘yyyy-MMM-dd’
)

Begin { }

Process {

foreach ($InputString in $Description) {
Write-Verbose “Processing string ‘$InputString’”
$Result = foreach ($Word in ($InputString -split $Delimiter)) {
try {
$IdentifiedDate = Get-Date $Word -Format $DesiredDateFormat -EA 1
Write-Verbose " Identified Date ‘$Word’, reformatting as ‘$IdentifiedDate’"
$IdentifiedDate
} catch {
$Word
}
}

$Result -join $Delimiter
}

}

End { }
}

$users = import-csv c:\temp\toRemove.csv

foreach ($user in $users) {
$User = Get-ADUser -Identity $user.samAccountName -Properties Description
$ChangedDescription = FindAndFormat-DateTime -Description $User.Description
Set-ADUser -Identity $user.samAccountName -Description $ChangedDescription
}

[/pre]