Running the following PowerShell returns false when I'd expect true:
$format = @('yyyy-MM-ddTHH:mm:ssZ', 'yyyy-MM-ddTHH:mm:sszzz', 'yyyy-MM-ddTHH:mm:ss')
$provider = [System.Globalization.CultureInfo]::InvariantCulture
$style = [System.Globalization.DateTimeStyles]::AllowWhiteSpaces -bor [System.Globalization.DateTimeStyles]::AssumeUniversal
$result = [DateTime]::MinValue
[DateTime]::TryParseExact('2020-01-01T12:01:00Z', $format, $provider, $style , [ref]$result)
# returns false
I've seen the same behaviour with both PowerShell (v5.1.19041.1682) and PWSH (v7.2.4).
If I pass a single value for the Format parameter instead of an array then I get the expected result:
$format = 'yyyy-MM-ddTHH:mm:ssZ'
$provider = [System.Globalization.CultureInfo]::InvariantCulture
$style = [System.Globalization.DateTimeStyles]::AllowWhiteSpaces -bor [System.Globalization.DateTimeStyles]::AssumeUniversal
$result = [DateTime]::MinValue
[DateTime]::TryParseExact('2020-01-01T12:01:00Z', $format, $provider, $style , [ref]$result)
# returns true
This isn't a bug in .net, as running the same in C# works exactly as one would expect (I've tried running the exact equivalent code as above too):
void Main()
{
var formats = new []{"yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-ddTHH:mm:sszzz", "yyyy-MM-ddTHH:mm:ss"};
var provider = System.Globalization.CultureInfo.InvariantCulture;
var style = System.Globalization.DateTimeStyles.AllowWhiteSpaces | System.Globalization.DateTimeStyles.AssumeUniversal;
foreach (var testString in new[]{"", "2020-01-01T12:01:00", "2020-01-01T12:01:00Z", "2020-01-01T12:01:00+01:00", "2020-01-01 12:01:00"})
{
var result = DateTime.MinValue;
if (DateTime.TryParseExact(testString, formats, provider, style, out result))
{
Console.WriteLine($"Parsed '{testString}' as {result}");
}
else
{
Console.WriteLine($"Failed to parse '{testString}'");
}
}
}
Output
Failed to parse ''
Parsed '2020-01-01T12:01:00' as 2020-01-01 12:01:00
Parsed '2020-01-01T12:01:00Z' as 2020-01-01 12:01:00
Parsed '2020-01-01T12:01:00+01:00' as 2020-01-01 11:01:00
Failed to parse '2020-01-01 12:01:00'
The issue is down to the Format parameter being seen as an array of objects instead of an array of strings. Include a cast to string array to resolve:
$format = [string[]]@('yyyy-MM-ddTHH:mm:ssZ', 'yyyy-MM-ddTHH:mm:sszzz', 'yyyy-MM-ddTHH:mm:ss')
If we run $format.GetType().FullName
on the original version we see that the type is System.Object[]
. By casting to [string[]]
we change this to System.String[]
, which then matches the expected signature / works as desired.
Full Code:
$format = [string[]]@('yyyy-MM-ddTHH:mm:ssZ', 'yyyy-MM-ddTHH:mm:sszzz', 'yyyy-MM-ddTHH:mm:ss')
$provider = [System.Globalization.CultureInfo]::InvariantCulture
$style = [System.Globalization.DateTimeStyles]::AllowWhiteSpaces -bor [System.Globalization.DateTimeStyles]::AssumeUniversal
$result = [DateTime]::MinValue
[DateTime]::TryParseExact('2020-01-01T12:01:00Z', $format, $provider, $style , [ref]$result)