powershelldatetimelocaledatetime-formatiso8601

How do I fix the date format In Powershell to use ISO 8601


I would like to change the default format of dates and times in Powershell to use the ISO 8601 format, so instead of displaying as dd/mm/yyyy, it would use yyyy-mm-dd

Please note: I do not want to have to specify anything on the date objects directly, as this will be annoying when there is a single date field on a returned object. I want to change the default formatting that will be used everywhere.

This is not answered by Windows ISO 8601 timestamp The answers there all involve working on the DateTime objects directly.

# NOT THIS
Get-Date -Format 'yyyy-mm-dd'

# NOR THIS
$d = Get-Date
$d.ToString('o')

The solution must work for Powershell 7 and above.

I have made the following attempts, but they both result in the errors shown.

Failed to set DateTimeFormat

(Get-Culture).DateTimeFormat = [cultureinfo]::InvariantCulture.DateTimeFormat

Output:

SetValueInvocationException: Exception setting "DateTimeFormat": "Instance is read-only."

Failed when calling Set-Culture

Set-Culture [cultureinfo]::InvariantCulture

Output:

Set-Culture: Cannot bind parameter 'CultureInfo'. Cannot convert value "[cultureinfo]::InvariantCulture" to type "System.Globalization.CultureInfo". Error: "Culture is not supported. (Parameter 'name')
[cultureinfo]::InvariantCulture is an invalid culture identifier."

Solution

  • (PowerShell 7.3.9)

    My solution is to change the LongDatePattern and LongTimePattern of DateTimeFormat on current thread.

    function Switch-DefaultTimeFormat {
        $culture = [CultureInfo]::InvariantCulture.Clone()
    
        # see https://learn.microsoft.com/en-us/dotnet/api/system.globalization.datetimeformatinfo?view=net-7.0
        $culture.DateTimeFormat.LongDatePattern = "yyyy-MM-dd"
        $culture.DateTimeFormat.LongTimePattern = "HH:mm:ss.fff"
    
        # optional: `ShortDatePattern`, `ShortTimePattern`, `FullDateTimePattern` can be changed too:
        #   $culture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd"
        #   $culture.DateTimeFormat.ShortTimePattern = "HH:mm:ss.fff"
        #   $culture.DateTimeFormat.FullDateTimePattern = "yyyy-MM-dd_HH:mm:ss.fff"
    
        $currentThread = [System.Threading.Thread]::CurrentThread
        $currentThread.CurrentCulture = $culture
        $currentThread.CurrentUICulture = $culture
    }
    

    Call this function to apply the new default date format. Invoke the function from profile script to "make it the default".

    See if it helps!

    Test and output:

    PS D:\> Get-Date
    
    Tuesday, 14 November 2023 3:38:17 pm
    
    PS D:\> Switch-DefaultTimeFormat
    PS D:\> Get-Date
    
    2023-11-14 15:38:17.838