我正在通过Media Created
以下方式从文件资源管理器中检索列字段:
$mCreated = $shellfolder.GetDetailsOf($shellfile, 208);
一切正常。它返回字符串“5/7/2017 4:09 PM”
问题:
当我尝试将字符串转换为格式化的日期时,出现此错误:
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
At C:\Client\testVideos\anotherTest.ps1:28 char:9
+ $formattedDate = [Datetime]::ParseExact("$mCreated".Trim(), ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
我尝试过的:
单独尝试了这些但都给出了相同的错误:
$formattedDate = [Datetime]::ParseExact("$mCreated".Trim(), 'yyyyMMddTHHmmss', $null)
$formattedDate = [Datetime]::ParseExact("$mCreated".Trim(), 'yyyyMMddTHHmmss', [Globalization.CultureInfo]::InvariantCulture)
# This line actually gives me a different error
$formattedDate = Get-Date "$mCreated".Trim() -Format "yyyyMMddTHHmmss"
# ERROR: Get-Date : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input
有效的方法:
我也一直Created Date
在使用相同的代码并以相同的方式格式化它,并且它可以起作用!
创建日期为“2021 年 2 月 12 日下午 1:10”、“2021 年 2 月 4 日下午 3:39”、“2021 年 2 月 2 日上午 9:00”或“2021 年 2 月 4 日下午 3:54”
# This formats it successfully with no error
$createdDate = $shellfolder.GetDetailsOf($shellfile, 4);
$formattedDate = $createdDate | Get-Date -Format "yyyyMMddTHHmmss"
相关但最终无益的:
https://stackoverflow.com/questions/42784919/parseexact-string-was-not-recognized-as-a-valid-datetime https://stackoverflow.com/questions/48637312/convert-string-to-powershell-datetime
答案1
我以前也遇到过同样的问题,该Folder.GetDetailsOf()
方法返回了各种日期。我发现问题是Unicode 格式字符
PS C:\> $TestFile = 'C:\Users\keith\Music\ABBA\Hits\03 Dancing Queen.wma'
>> $ofolder = $Shell.NameSpace((Split-Path $TestFIle))
>> $oFile = $oFolder.ParseName((Split-Path $TestFile -Leaf))
>>
>> $MediaCreated = $oFolder.GetDetailsOf($oFile, 208)
>> $MediaCreated
>> $MediaCreated.Length
>> [Int[]][Char[]]$MediaCreated -join '-'
>>
6/19/2010 11:54 PM
23
8206-54-47-8206-49-57-47-8206-50-48-49-48-32-8207-8206-49-49-58-53-52-32-80-77
PS C:\>>[DateTime]$MediaCreated
Cannot convert value "6/19/2010 11:54 PM" to type "System.DateTime". Error:
"String was not recognized as a valid DateTime."
At line:1 char:1
+ [DateTime]$MediaCreated
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider
我的解决方案是在正则表达式中将有效的 DateTime 字符列入“白名单”。因此,正则表达式匹配的“好”字符如下:
\w
任何单词字符(0..9、“A”、“P”和“M”)\:
冒号(时间分隔符)/
斜线(日期分隔符)- 空间
分隔符可能因地区而异。为了简单、简洁和省事,我硬编码为美国。
这些可以组合起来并用括号括起来以创建一个字符类将匹配有效的人物。:
[\w\:/ ]
反转类别并匹配无效的字符,在类定义前添加一个插入符号:
[^\w\:/ ]
然后我们可以使用-更换操作员 删除它们:
[DateTime]($MediaCreated -replace '[^\w\:/ ]','')
PS C:\> $MediaCreated = [DateTime]($MediaCreated -replace '[^\w\:/ ]','')
PS C:\>>$MediaCreated
Saturday, June 19, 2010 11:54:00 PM
PS C:\>>$MediaCreated.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType
最近才了解到替代方案:ShellFolderItem.ExtendedProperty()
从项目的属性集中获取属性的值。可以通过名称或属性集的格式标识符 (FMTID) 和属性标识符 (PID) 指定属性。
返回值类型:Variant*
此方法返回时,包含属性的值(如果指定项存在)。该值将具有完整类型 — 例如,日期将以日期形式返回,而不是字符串。
如果属性有效但对于指定的项目不存在,则此方法返回零长度字符串,否则返回错误代码。
备注 指定属性有两种方法。第一种方法是将属性的已知名称(如“Author”或“Date”)分配给 sPropName。但是,每个属性都是组件对象模型 (COM) 属性集的成员,也可以通过指定其格式 ID (FMTID) 和属性 ID (PID) 来标识。FMTID 是标识属性集的 GUID,PID 是标识属性集中特定属性的整数。
通过属性的 FMTID/PID 值指定属性通常比使用其名称更有效。要将属性的 FMTID/PID 值与 ExtendedProperty 一起使用,必须将它们组合成 SCID。SCID 是一个字符串,其中包含“FMTID**PID”格式的 FMTID/PID 值,其中 FMTID 是属性集 GUID 的字符串形式。例如,摘要信息属性集的作者属性的 SCID 为“{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4”。
我找不到“Media Created”的正确名称,但 * FMTID/PID* 对是"{2E4B640D-5019-46D8-8881-55414CC5CAA0}100"
:
PS C:\>>$oFile.ExtendedProperty("MediaCreated")
PS C:\> $oFile.ExtendedProperty("Media Created")
PS C:\> $oFile.ExtendedProperty("MediaEncoded")
PS C:\> $oFile.ExtendedProperty("MediaCreationDate")
PS C:\> $oFile.ExtendedProperty("System.MediaEncoded")
PS C:\>>$oFile.ExtendedProperty("{2E4B640D-5019-46D8-8881-55414CC5CAA0}100")
Sunday, June 20, 2010 04:54:26 AM
PS C:\>>($oFile.ExtendedProperty("{2E4B640D-5019-46D8-8881-55414CC5CAA0}100")).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType
答案2
继续我的评论,顺便说一句,您也可以这样做进行格式化。
($mCreated = (Get-Date -Format g).ToString())
# Results
<#
2/16/2021 11:10 AM
#>
($mCreated).GetType() |
Format-Table -AutoSize
# Results
<#
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
#>
$mCreated |
Get-Member
# Results
<#
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
...
Chars ParameterizedProperty char Chars(int index) {get;}
Length Property int Length {get;}
#>
将日期字符串转换为日期时间对象
([DateTime]$mCreated = ((Get-Date -Format g).ToString()))
# Results
<#
Tuesday, February 16, 2021 11:12:00 AM
#>
($mCreated).GetType() |
Format-Table -AutoSize
# Results
<#
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType
#>
$mCreated |
Get-Member
# Results
<#
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
...
ToUniversalTime Method datetime ToUniversalTime()
Date Property datetime Date {get;}
Day Property int Day {get;}
DayOfWeek Property System.DayOfWeek DayOfWeek {get;}
DayOfYear Property int DayOfYear {get;}
Hour Property int Hour {get;}
Kind Property System.DateTimeKind Kind {get;}
Millisecond Property int Millisecond {get;}
Minute Property int Minute {get;}
Month Property int Month {get;}
Second Property int Second {get;}
Ticks Property long Ticks {get;}
TimeOfDay Property timespan TimeOfDay {get;}
Year Property int Year {get;}
DateTime ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Date")...
#>
更多详情请见:
- https://adamtheautomator.com/demystifying-powershell-dates-datetime-and-formatting
- https://adamtheautomator.com/powershell-conver-string-date-casting/#Converting_a_String_to_a_Date
- http://winpowershell.blogspot.com/2006/09/systemdatetime-parseexact.html#!/2006/09/systemdatetime-parseexact.html
- http://powershell.com/cs/blogs/tips/archive/2013/02/07/parsing-custom-date-and-time-formats.aspx
至于具有 parseexact 的字符串。它受系统日期设置方式的影响,并且 yeat 必须位于时间戳的开头或结尾。请在此处查看详细信息:
[datetime]::ParseExact("20181010134412",'yyyyMMddHHmmss',$null)
# Results
<#
Wednesday, October 10, 2018 1:44:12 PM
#>
($mCreated).GetType() |
Format-Table -AutoSize
# Results
<#
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
#>
[datetime]::ParseExact($mCreated,'yyyyMMddHHmmss',$null)
[datetime]::ParseExact($($mCreated),'yyyyMMddHHmmss',$null)
# Results
<#
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
#>
$mCreated
# Results
<#
2/16/2021 11:24 AM
#>
[datetime]::ParseExact('20210216112400','yyyyMMddHHmmss',$null)
[datetime]::ParseExact('02161124002021','MMddHHmmssyyyy',$null)
# Results
<#
Tuesday, February 16, 2021 11:24:00 AM
Tuesday, February 16, 2021 11:24:00 AM
#>
或者你最终会到达这里:
$mCreated = '16/02/2021 9:11 AM'
([datetime]::ParseExact($mCreated,'dd/MM/yyyy h:mm tt',$null))
$mCreated = '02/16/2021 9:11 AM'
([datetime]::ParseExact($mCreated,'MM/dd/yyyy h:mm tt',$null))
# Results
<#
Tuesday, February 16, 2021 9:11:00 AM
Tuesday, February 16, 2021 9:11:00 AM
#>
详细信息请见此处:
尝试使用调用中的日期字符串时,存在无法打印/不可见字符的问题。
$FileInformation = Get-ItemProperty -Path 'F:\Videos\2020 03 19 Competitive Intel.mp4'
$ShellApplication = New-Object -ComObject Shell.Application
$ShellFolder = $ShellApplication.Namespace($FileInformation.Directory.FullName)
$ShellFile = $ShellFolder.ParseName($FileInformation.Name)
$MetaDataProperties = [ordered] @{}
0..400 |
ForEach-Object -Process {
$DataValue = $ShellFolder.GetDetailsOf($null, $_)
$PropertyValue = (Get-Culture).TextInfo.ToTitleCase($DataValue.Trim()).Replace(' ', '')
if ($PropertyValue -ne '')
{$MetaDataProperties["$_"] = $PropertyValue}
}
$MetaDataProperties.Values -Match 'media'
# Results
<#
MediaCreated
#>
###
($MediaCreated = $ShellFolder.GetDetailsOf($ShellFile , 208))
($DateCreated = $ShellFolder.GetDetailsOf($ShellFile , 4))
($MediaCreated).GetType()
($DateCreated).GetType()
# Results
<#
19-Mar-20 17:30
03-Dec-20 13:05
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
True True String System.Object
#>
($TestDate = Get-Date(Date) -Format g)
($TestDate1 = Get-Date(Date) -Format g) -replace '-|\s|:'
# Results
<#
17-Feb-21 16:41
17Feb211641
#>
([datetime]::ParseExact($TestDate,'dd-MMM-yy HH:mm',$null))
([datetime]::ParseExact($TestDate1,'dd-MMM-yy HH:mm',$null))
# Results
<#
Wednesday, 17 February, 2021 16:54:00
Wednesday, 17 February, 2021 16:54:00
#>
(('17-Feb-21 16:41').ToCharArray()).Count
# Results
<#
15
#>
([datetime]::ParseExact($MediaCreated,'dd-MMM-yy HH:mm',$null))
# Results
<#
Exception calling "ParseExact" with "3" argument(s): "String was not recognized
as a valid DateTime."
#>
在常规 cmd.exe(而不是来自 PowerShell(ISE/consolehost)或通过 Windows 终端的 cmd.exe)中,存在记事本/consolehost/ISE/VSCode/Windows 终端中不会出现的不可打印/不可见字符。
(($MediaCreated).ToCharArray()).Count
# Results
<#
20 # multiple hidden/non-printable characters
#>
($MediaCreated).ToCharArray()
# Results
<#
1
9
-
M
a
r
-
2
0
1
7
:
3
0
#>
(($MediaCreated).ToCharArray())[0]
(($MediaCreated).ToCharArray())[1]
(($MediaCreated).ToCharArray())[2]
(($MediaCreated).ToCharArray())[3]
# Results
<#
1
9
-
#>
($MediaCreated).ToCharArray() |
ForEach{ [int][char]$PSItem }
# Results
<#
8206
49
57
45
8206
77
97
114
45
8206
50
48
32
8207
8206
49
55
58
51
48
#>
这就是 Keiths 的正则表达式有效的原因......
([datetime]::ParseExact(($MediaCreated -replace '[^\w\:/ ]'),'ddMMMyy HH:mm',$null))
# Results
<#
Thursday, 19 March, 2020 17:30:00
#>
...因此我们可以更直接地获得它,以允许 parseexact 工作,而不必改变数据类型:
$FileInformation = Get-ItemProperty -Path 'F:\Videos\2020 03 19 Competitive Intel.mp4'
$ShellApplication = New-Object -ComObject Shell.Application
$ShellFolder = $ShellApplication.Namespace($FileInformation.Directory.FullName)
$ShellFile = $ShellFolder.ParseName($FileInformation.Name)
($MediaCreated = $ShellFolder.GetDetailsOf($ShellFile , 208))
($DateCreated = $ShellFolder.GetDetailsOf($ShellFile , 4))
# Results
<#
19-Mar-20 17:30
03-Dec-20 13:05
#>
($MediaCreated).GetType()
($DateCreated).GetType()
# Results
<#
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
True True String System.Object
#>
([datetime]::ParseExact(($MediaCreated -replace '[^\w\:/ ]'),'ddMMMyy HH:mm',$null))
([datetime]::ParseExact(($DateCreated -replace '[^\w\:/ ]'),'ddMMMyy HH:mm',$null))
# Results
<#
Thursday, 19 March, 2020 17:30:00
Thursday, 3 December, 2020 13:05:00
#>
($MediaCreated).GetType()
($DateCreated).GetType()
# Results
<#
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
True True String System.Object
#>