how do you convert a date string that contains a monthname to a datetime?

222 Views Asked by At

I am sure this ust be simple, but the search engines lead me articals that answer everything but this :-(

I have a string "13 February 2023 13:45:40" that I need to convert to a datetime so I may do a comparison

How you cast a date like this? Does it need a specialist module thats a little smarter then me hacking around with parseextract or regex?

Thanks oh wise ones

2

There are 2 best solutions below

0
Mathias R. Jessen On

The date format specifier for the full month name is MMMM, use this with [datetime]::ParseExact():

$dateString   = "13 February 2023 13:45:40"
$formatString = 'dd MMMM yyyy HH:mm:ss'
$cultureInfo  = [cultureinfo]::GetCultureInfo('en-US')

[datetime]::ParseExact($dateString, $formatString, $cultureInfo)

Replace en-US with the appropriate culture identifier if you need to parse timestamps in other languages:

$dateString   = "13 février 2023 13:45:40"
$formatString = 'dd MMMM yyyy HH:mm:ss'
$cultureInfo  = [cultureinfo]::GetCultureInfo('fr-FR')

[datetime]::ParseExact($dateString, $formatString, $cultureInfo)
0
mklement0 On
  • 13 February 2023 13:45:40 uses a string format that is directly recognized as a standard format by the invariant culture ([cultureinfo]::InvariantCulture, an immutable culture meant for programmatic use, based on - but distinct from - the en-US culture).

  • Using a [datetime] cast in PowerShell always uses the invariant culture, so a cast with a standard format recognized by that culture can safely be used irrespective of what the current culture is.

    • Caveat: Passing such strings to Get-Date's -Date parameter is not safe, because they are subject to interpretation by the current culture's rules first, due to an unfortunate inconsistency in PowerShell's parameter-binding that won't be fixed, for the sake of backward compatibility - see GitHub issue #6989

Therefore:

[datetime] "13 February 2023 13:45:40"

To handle formats not recognized by the invariant culture:

  • If they are standard formats recognized by the current / a specific culture, use [datetime]::Parse():

    • Use [datetime]::Parse($string) to parse based on the current culture.

    • Use, e.g., [datetime]::Parse($string, [cultureinfo] 'fr-FR') to parse based on a given culture, such as fr-FR (French, France) in this example.

  • Otherwise, custom parsing based on custom format strings passed to [datetime]::ParseExact() is required, as shown in Mathias' helpful answer.

    • Note: To perform custom parsing based on the invariant culture, use
      [cultureinfo] '' (sic) as the provider argument.
  • Both methods above also have Try-prefixed variants, which signal via a [bool] return value whether parsing is possible, and accept an optional [ref] argument to receive the result of the conversion.

A few examples, all of which are equivalent:

# The input string.
$dateString = '13 February 2023 13:45:40'

# OK - the [datetime] cast automatically recognizes the format 
# in the context of the *invariant* culture.
[datetime] $dateString

# Ditto, referencing the invariant culture explicitly.
[datetime]::Parse($dateString, [cultureinfo]::InvariantCulture)

# Ditto, with an explicit format string, using [cultureinfo] ''
# as a more concise alternative to [cultureinfo]::InvariantCulture
[datetime]::ParseExact($dateString, 'dd MMMM yyyy HH:mm:ss', [cultureinfo] '')

# .Try*() variants.

# Initialize the result variable.
# For the method-overload resolution below to work as expected,
# be sure to type-constrain it as [datetime].
[datetime] $dtResult = 0

# .TryParse()
$ok = [datetime]::TryParse(
  $dateString, 
  [cultureinfo]::InvariantCulture, 
  [ref] $dtResult
)
# Result
[pscustomobject] @{
  CouldParse = $ok
  Result = $dtresult
}

# .TryParseExact()
$ok = [datetime]::TryParseExact(
  $dateString,
  'dd MMMM yyyy HH:mm:ss', 
  [cultureinfo] '',
  'None',   # [System.Globalization.DateTimeStyle]::None
  [ref] $dtResult
)
# Result
[pscustomobject] @{
  CouldParse = $ok
  Result = $dtresult
}