Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
980 views
in Technique[技术] by (71.8m points)

datetime - File date metadata not displaying properly

I have been trying to write a Powershell script based on some code online that will read the metadata info from picture, video and other files and then sort them based on one of the dates (date taken currently seems to be the best bet if it's available, but date modified works on files that have not yet been altered).

However, when I run the script and pull the info, I can't convert the string to a date. Here's roughly how I get the info through a COM object:

PS C:/> $objShell = New-Object -ComObject Shell.Application
PS C:/> $objFolder = $objShell.namespace("C:MyFolder")
PS C:/> $date = $objFolder.GetDetailsOf($objFolder.Items().Item(0), 12)
PS C:/> $date

7/?10/?2014 ??7:09 PM

The problem is I should be able to convert this to a datetime object. For instance, if I manually write it in it works:

PS C:/> [datetime]::ParseExact("7/10/2014 7:09 PM","g",$null)

Thursday, July 10, 2014 7:09:00 PM

But if I substitute the variable it doesn't work:

PS C:/> [datetime]::ParseExact($date,"g",$null)
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
At line:1 char:1
+ [datetime]::ParseExact($date,"g",$null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FormatException

This is most likely due to the fact that the variable isn't actually what I'm seeing. It's in fact longer. Not to mention the fact that if you iterate through all the characters, you can see where the extra length is coming from:

PS C:> $date.Length #should be about 16, you'd think

22

PS C:> $datearray = @()
PS C:> for ($i = 0; $i -lt $date.Length; $i++) {$datearray += $date[$i]}
PS C:> $datearray #i'm printing on one line and in quotes for ease of viewing

" 7/ 10/ 2014   7:09 PM"

If you try printing the array with a join or something similar, the results are (to me, without knowing what's going on) unpredictable. It treats it like it has 22 characters, but prints ignoring the spaces.

I'm sure I could spend a bit of time and do some string formatting, but I'd rather just be able to parse the given date. What's going on?

Edit: I'm able to access the file info easily, though I prefer not to. I'm mainly focusing on why the results I'm seeing are inconstant and showing a length that doesn't match how it prints out, and how I can deal with them. If nothing else, I'm curious as to what is going on.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I wanted to know what the extra characters were ( you dont mention already looking at this. ). I Updated your array code $datearray += $date[$i] to $datearray += [int][char]$date[$i]. The truncated output showed two oddities 8207 and 8206 which translate to left-to-right mark and right-to-left mark. They are normally associated with html. Unfortunately i cannot provide insight to their presense. Good news is that they are easy to remove.

$date = ($date -replace [char]8206) -replace [char]8207
[datetime]::ParseExact($date,"g",$null)

Which nets the output

Thursday, March 26, 2009 1:43:00 PM

Hopefully this is a little bit closer of what you wanted. I tried searching for reasons for the presence of those ascii codes but i didn't find anything useful.

Extra Information for other readers

I did this since i didnt know what the index 12 was. So i made an array that contains the friendly names of all the file meta data possible (288 entries!). I have the here-string located here for brevity.

With this i was testing the following code against a picture of mine.

$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace("C:Temp")
0..$Meta.GetUpperBound(0)| %{
    $metaValue = $objFolder.GetDetailsOf($objFolder.Items().Item(2), $_)
    If ($metaValue) {Write-Host "$_ - $($meta[$_]) - $metaValue"}
    } 

$Meta is the array i spoke of earlier. The code will cycle though all the details of my file, indicated by Item(2), writing to screen all file details that contain values. In the end there is a line converting the string to a date value. Script output below

0 - Name - IMG_0571.JPG
1 - Size - 3.12 MB
2 - Item type - JPEG image
3 - Date modified - 3/26/2009 3:34 PM
4 - Date created - 8/24/2014 5:19 PM
5 - Date accessed - 8/24/2014 5:19 PM
6 - Attributes - A
9 - Perceived type - Image
10 - Owner - TE_STCameron
11 - Kind - Picture
12 - Date taken - ?3/?26/?2009 ??1:43 PM
19 - Rating - Unrated
30 - Camera model - Canon EOS DIGITAL REBEL XS
31 - Dimensions - ?3888 x 2592?
32 - Camera maker - Canon
53 - Computer - TE_ST (this computer)
155 - Filename - IMG_0571.JPG
160 - Bit depth - 24
161 - Horizontal resolution - ?72 dpi
162 - Width - ?3888 pixels
....output truncated....
247 - Program mode - Normal program
250 - White balance - Auto
269 - Sharing status - Not shared

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...