Home > Net >  Using Powershell [DateTime]::ParseExact - Funny Strings?
Using Powershell [DateTime]::ParseExact - Funny Strings?

Time:12-04

Good afternoon Powershell wizards!

I am hoping someone can explain to me how I can fix this issue, and more importantly what the issue actually is!

I'm attempting to fix an old script I wrote years ago that searches for several dates on a files properties and picks one to use for renaming that file.

The issue I'm having is that when I use parseExact it fails for the date strings read from the files... but it works if I manually type the same string into powershell!

Please note that this script is only going to be ran on my PC and only needs to work with dates from my files formats so I'm not too worried about use of $null unless it's related.

See example below:

Write-Host "TEST 1"
$DateTime = [DateTime]::ParseExact("240720211515","ddMMyyyyHHmm",$null)
Write-Host $DateTime # WORKS!

Write-Host "TEST 2"
$DateTime2 = [DateTime]::ParseExact("‎24‎07‎2021‏1515","ddMMyyyyHHmm",$null)
Write-Host $DateTime2 # FAILS!

Looks the same right?

Here is a more real world example of what I'm up to that fails

$file = Get-Item "C:\SomeFolder\somefile.jpg"
$shellObject = New-Object -ComObject Shell.Application
$directoryObject = $shellObject.NameSpace( $file.Directory.FullName )
$fileObject = $directoryObject.ParseName( $file.Name )

$property = 'Date taken'
for(
    $index = 5;
    $directoryObject.GetDetailsOf( $directoryObject.Items, $index ) -ne $property;
      $index) { }

$photoDate = $directoryObject.GetDetailsOf($fileObject, $index)
Write-Host $photoDate # <-- This reads ‎03/‎08/‎2021 ‏‎09:15
$output = [DateTime]::ParseExact($photoDate,"dd/MM/yyyy HH:mm",$null) # <-- This fails
Write-Host $output

# If i manually type in here it works.... If I copy and paste from the Write-Host it fails...
$someInput = "03/08/2021 09:15"
$workingOutput = [DateTime]::ParseExact($someInput,"dd/MM/yyyy HH:mm",$null)
Write-Host $workingOutput

CodePudding user response:

For anyone else who comes across this, it seems like there are invisible characters being added. Thanks for the spot @SantiagoSquarzon

This fixes it for my particular purposes:

$photoDate = $directoryObject.GetDetailsOf($fileObject, $index)
$utfFree = $photoDate -replace "\u200e|\u200f", ""

CodePudding user response:

I ran into this issue when I started exploring metadata with PowerShell. My solution was to create a regex "inverted whitelist" character class and delete (replace with '') all non-whitelist characters.

But then I learned of an alternate method avaiable to FolderItem obejcts: the ExtenedProperty() method.

Gets the value of a property from an item's property set. The property can be specified either by name or by the property set's format identifier (FMTID) and property identifier (PID).

It's primary strength being the feturn type corresponds to the property value type:

When this method returns, contains the value of the property, if it exists for the specified item. The value will have full typing—for example, dates are returned as dates, not strings.

Using this method to access date properties eliminates string parsing and the issues you encountered:

PS Pictures> $FileInfo = Get-Item "C:\Users\keith\Pictures\Leland\2009\Leland 191.JPG"
PS Pictures> $Shell    = New-Object -ComObject shell.application
PS Pictures> $comFolder = $Shell.NameSpace($FileInfo.DirectoryName)
PS Pictures> $comFile   = $comFolder.ParseName($FileInfo.Name)
PS Pictures>
PS Pictures> $comFolder.GetDetailsOf($null,12)
Date taken
PS Pictures> $comFolder.GetDetailsOf($comFile,12)
‎9/‎5/‎2009 ‏‎2:06 PM
PS Pictures> $comFolder.GetDetailsOf($comFile,12).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS Pictures> $comFile.ExtendedProperty("DateTaken")
PS Pictures> $comFile.ExtendedProperty("System.Photo.DateTaken")

Saturday, September 5, 2009 07:06:41 PM


PS Pictures> $comFile.ExtendedProperty("System.Photo.DateTaken").GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType

It also returns arrays for properties than can contain multiple values (Tags, Contributing Artists, etc/):

PS Pictures> $comFolder.GetDetailsOf($null,18)
Tags
PS Pictures> $comFolder.GetDetailsOf($comFile,18)
Leland; Tim; Jorge
PS Pictures> $comFolder.GetDetailsOf($comFile,18).GetTYpe()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS Pictures> $comFile.ExtendedProperty("System.KeyWords")
PS Pictures> $comFile.ExtendedProperty("System.Keywords")
Leland
Tim
Jorge
PS Pictures> $comFile.ExtendedProperty("System.Keywords").GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String[]                                 System.Array

But GetDetailsOf() is still useful, particularly for values that use an EnumList:

PS Pictures> $comFolder.GetDetailsOf($null,261)
Flash mode
PS Pictures> $comFolder.GetDetailsOf($comFile,261)
No flash, auto
PS Pictures> $comFile.ExtendedProperty("System.Photo.Flash")
24
  • Related