Search code examples
powershelldatetimeregistrydatetime-format

Powershell Registry String to Workable Date


Cannot convert string format to date using parse exact.

Registry contains the following string value: 2022-10-18T12:40:25

I need to convert this string to a date field in order to count number of days since (compared to today).


$startdate = 
  Get-ItemProperty -Path 'HKLM:SOFTWARE\Adobe\Acrobat Distiller\DC\Installer\' |
  select-object 'Dummy'


[datetime]::parseexact($startdate,'dd/MM/yyyy HH:mm',$null)

$today = (([datetime]::Now))
$x = New-TimeSpan -Start $startdate -End $today
"$($x.days) $("days have passed since") $($startdate)"
Cannot find an overload for "parseexact" and the argument count: "3".
At line:2 char:1
+ [datetime]::parseexact($startdate,'dd/MM/yyyy HH:mm',$null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest
 
New-TimeSpan : Cannot bind parameter 'Start'. Cannot convert value "@{dummy=2022-10-18T12:40:25}" to type "System.DateTime". Error: "Cannot convert the "@{dummy=2022-10-18T12:40:25}" value of type 
"Selected.System.Management.Automation.PSCustomObject" to type "System.DateTime"."
At line:5 char:26
+ $x = New-TimeSpan -Start $startdate -End $today
+                          ~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-TimeSpan], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.NewTimeSpanCommand
 
 days have passed since @{dummy=2022-10-18T12:40:25}



Solution

  • Your primary problem is that you need to use -ExpandProperty, if you use Select-Object, or you can use simple property access:

    • Select-Object (select) by default returns a [pscustomobject] instance that has the requested properties - even when you're only asking for a single property. To get only that property's value, use the -ExpandProperty parameter instead of the (possibly positionally implied) -Property parameter - see this answer for details and alternatives, notably the ability to simply use (...).SomeProperty

    Therefore, the simplest solution is:

    $startdate = (
      Get-ItemProperty 'HKLM:SOFTWARE\Adobe\Acrobat Distiller\DC\Installer'
    ).Dummy
    

    Or, in PSv5+, using Get-ItemPropertyValue:

    $startdate =
      Get-ItemPropertyValue 'HKLM:SOFTWARE\Adobe\Acrobat Distiller\DC\Installer' Dummy
    

    As for then parsing the resulting string into a [datetime] instance:

    The format string you're passing to ::ParseExact(), doesn't match your input string, and TheMadTechnician's answer shows how to fix that (see this answer's bottom section for further considerations).

    However, you can more simply use a [datetime] cast, which recognizes your string format as-is, irrespective of what culture is currently in effect:

    [datetime] '2022-10-18T12:40:25'
    

    In essence, PowerShell translates the above into the following ::Parse() call:

    [datetime]::Parse('2022-10-18T12:40:25', [cultureinfo]::InvariantCulture)
    

    In general, for full robustness when using format strings, it is best to escape :, /, and . (if present) with \, so as if they are to be interpreted literally, i.e by only matching literally during parsing and being included literally when formatting output (by default, they're considered placeholders for the target culture's separators):

    [datetime]::ParseExact(
      '2022-10-18T12:40:25', 
      'yyyy-MM-ddTHH\:mm\:ss',  # \-escaping ensures literal matching
      [cultureinfo]::InvariantCulture
    )
    

    Note: In this particular case, [cultureinfo]::InvariantCulture alone would be sufficient for robustness, given that this culture uses : as the time separator.