Search code examples
.netpowershelliso8601

In PowerShell, how do I convert an ISO 8601 timestamp that uses a comma as the fractional second separator to a native datetime object?


If I have an ISO 8601-compliant timestamp that uses a comma as the fractional second seperator, e.g.:

$strTimestamp = '2021-08-31T23:12:11,5-05:00'

(i.e., 2021-08-31 at 23:12:11 and 0.5 seconds, UTC-5 offset)

How do I convert this to native PowerShell datetime? I've tried:

Get-Date -Date $strTimestamp

but it throws an error:

Get-Date: Cannot bind parameter 'Date'. Cannot convert value "2021-08-31T23:12:11,5-05:00" to type "System.DateTime". Error: "String '2021-08-31T23:12:11,5-05:00' was not recognized as a valid DateTime."

It's worth noting that the same timestamp with a period instead of a comma works just fine:

(Get-Date -Date '2021-08-31T23:12:11.5-05:00') | Format-List

Returns:

DisplayHint : DateTime
Date        : 8/31/2021 12:00:00 AM
Day         : 31
DayOfWeek   : Tuesday
DayOfYear   : 243
Hour        : 23
Kind        : Local
Millisecond : 500
Minute      : 12
Month       : 8
Second      : 11
Ticks       : 637660483315000000
TimeOfDay   : 23:12:11.5000000
Year        : 2021
DateTime    : Tuesday, August 31, 2021 11:12:11 PM

Since the comma separator is compliant with the standard, an ideal answer would accept a comma, a period, or no separator at all.

Thanks!


Solution

  • Pragmatically speaking, replacing , with . in your input strings is indeed the simplest solution your case:

    '2021-08-31T23:12:11,5-05:00', # comma
    '2021-08-31T23:12:11.4-05:00', # period
    '2021-08-31T23:12:11-05:00' |  # no fractional part
      ForEach-Object {
        [datetime] ($_ -replace ',', '.')
      }
    

    While , as the decimal mark for fractional seconds is part of the ISO 8601 standard, as you state, the [datetime] (System.DateTime) type's Parse() method doesn't recognize it (it only recognizes .), irrespective of the culture in effect - at least as of .NET 5 / the preview versions of .NET 6.

    Note that PowerShell's [datetime] '...' cast is the equivalent of calling
    [datetime]::Parse('...', [cultureinfo]::InvariantCulture), because PowerShell applies the invariant culture by default (see this answer for an overview of PowerShell's casts in general).