Convert date format from DD.MM.YYYY to YYYY-MM-DD

Viewed 2775

I have folders on the disk in the german format: "01.05.2019", which I want to convert into the english format: "2019-05-01".

I am using PowerShell. Is there a fancy function for doing this? Or should I get all substrings and reorder them?

Currently I only collect the strings:

$OrgDir = "P:\Fotos\Import"
$folders = Get-ChildItem $($OrgDir) -Directory 
foreach ($dir in $folders) {
    Write-Host "folder: " $dir
}
3 Answers

Use [DateTime]::ParseExact() to avoid the date parser mixing up the month and day:

$OrgDir = "P:\Fotos\Import"
$folders = Get-ChildItem $OrgDir -Directory
foreach ($dir in $folders) {
    Write-Host "folder: $([DateTime]::ParseExact($dir.Name, "dd.MM.yyyy", $null).ToString("yyyy-MM-dd"))"
}

The above prints out the converted names. To efficiently rename the files however, I recommend this:

Get-ChildItem $OrgDir -Directory | 
    ForEach-Object {
        $_ | Rename-Item -NewName (
            [DateTime]::ParseExact($_.Name, "dd.MM.yyyy", $null).ToString("yyyy-MM-dd")
        )
    }

This line of PowerShell renames all directories at $OrgDir to the new date format, given that all directories in the folder are named this way.

Reference


UPDATE:

As @Matt Johnson pointed out, $null uses your system default culture for ParseExact(string, format, culture) (as well as ToString(format, culture)). This may or may not cause problems based on what culture setting your system currently has.

To ensure these settings do not interfere with this function, use [System.Globalization.CultureInfo]::InvariantCulture for the culture parameters in both ParseExact() and ToString().

Matt Johnson provides important pointers in his comments:

To write robust code that works independently of what culture is in effect, specify the culture context explicitly, both when:

  • parsing strings as [datetime] instances

  • formatting [datetime] instances as strings

Therefore, use the following in your case:

PS> [datetime]::Parse('01.05.2019', [cultureinfo] 'de-DE').
      ToString('yyyy-MM-dd', [cultureinfo]::InvariantCulture)
2019-05-01
  • Since 01.05.2019 is a valid (day-first) short date in German, no custom parsing is needed, only de-DE (German / Germany) as the cultural context.

  • .ToString('yyyy-MM-dd', [cultureinfo]::InvariantCulture) specifies an explicit output-format string; [cultureinfo]::InvariantCulture - the invariant culture (based on US-English) - as the cultural context ensures that the date is interpreted based on the Gregorian calendar.

Note that in PowerShell casts (e.g., [datetime] '01.05.2019') and string interpolation (e.g., "$(get-date)") always use the invariant culture - whereas calling [datetime]::Parse() and .ToString() without an explicit culture (format-provider) argument uses the current culture.

Finally this did the trick for me:

PS> [datetime]::Parse('01.05.2019', [cultureinfo] 'de-DE').
      ToString('yyyy-MM-dd', [cultureinfo]::InvariantCulture)

All other solutions ended in:

Get-Date : Cannot bind parameter 'Date'. Cannot convert value "15.12.2019" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."

Thanks a lot mklement0.

Related