3

When i'm trying to parse a line in a IIS log file and pulling the datetime on the line, I'm getting the following error

Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime." At line:9 char:1

  • $dateTime = [datetime]::ParseExact($dateTimeString, 'yyyy-MM-dd HH:mm ...
  •   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : FormatException
    

here is my powershell code:

$line = '2020-12-23 02:01:16.244 -06:00 [Information] 2020-12-23T08:01:16.2446161Z:     [Error] Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Connection request timed out'
$dateTimeString = [regex]::Matches($line, '\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d')[0].Groups[1].Value
write-host "datetimestr:" $dateTimeString
$provider = New-Object System.Globalization.CultureInfo "en-US"
$dateTime = [datetime]::ParseExact($dateTimeString, 'yyyy-MM-dd HH:mm:ss', $provider)

write-host $dateTime
$dateTime -f 'MM/dd/yyyy HH:mm:ss' | write-host 

i guess i need some fresh eyes to see what i'm missing.

notes:

  • i've tried copying and pasting the string in the $line var to validate there are no strange chars in the datetime
  • i have tried adding .trim to the $line and that didn't help
  • i've also narrowed the regex pattern to '\d\d\d-\d\d-\d\d' and parseexact() to ($dateTimeString, 'yyyy-MM-dd', $provider) and this doesn't help either.
phill
  • 13,434
  • 38
  • 105
  • 141

2 Answers2

3

Just to offer a simpler solution that doesn't require a complex regex:

$line = '2020-12-23 02:01:16.244 -06:00 [Information] 2020-12-23T08:01:16.2446161Z:     [Error] Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Connection request timed out'

[datetime] ((-split $line)[0..1] -join ' ')
  • -split, the string-splitting operator is used to split the line into whitespace-separated tokens, and the first two tokens ([0..1]) are joined back with a space.

  • [datetime] is a culture-invariant way of converting a date-time string into a [datetime] (System.DateTime) instance; this culture-invariant way is based on the InvariantCulture, which is based on the US-English culture.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

You can use

$dateTimeString = [regex]::Match($line, '\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d').Value

Your [regex]::Matches($line, '\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d')[0].Groups[1].Value code matches a datetime substring into Group 0. You are trying to get Group 1 value by using .Groups[1].Value, but there is no capturing group defined in the pattern.

Note there is no need using Matches that fetches all occurrences in the string since all you need is the first match, which can be done with a mere Match.

Also, repeating \d four times in a regex is really redundant, you may use a {4} limiting quantifier.

If you want to only find a match at the start of the string, add ^ at the beginning: '^\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d'.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563