将字符串解析为日期时间格式

时间:2019-04-25 09:42:45

标签: powershell

我将在计算机上获取所有已安装的软件,并将结果打印到HTML表中。但是很多日期都采用yyyyMMdd格式,但是我想使用yyyy-MM-dd格式。

Windows 10
Powershell版本-5.1.17

$Soft = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*;
#$Soft64 =  Get-ItemProperty HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*;
$InstallDate = $Soft | Select-Object InstallDate;

for ($i = 0; $i -lt $InstallDate.Length; $i++) {
    if ($InstallDate[$i] -match '-') {
        $InstallDate[$i]
    } else {
        $InstallDate = [DateTime]::ParseExact($InstallDate[$i], 'yyyyMMdd', $null)
        $InstallDate.ToString('yyyy-MM-dd')
    }
}

列表中的一个日期格式正确(2019-04-01),或者它们为空/空,执行脚本后,我得到以下结果:

InstallDate
-----------
2019-04-01

但是不包含-的日期,例如20190319,抛出错误:

Cannot find an overload for "ParseExact" and the argument count: "3".
At C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:12 char:9
+         $InstallDate = [datetime]::ParseExact($InstallDate[$i], 'yyyy ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

Cannot find an overload for "ToString" and the argument count: "1".
At C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:13 char:9
+         $InstallDate.ToString('yyyy-MM-dd')
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

2 个答案:

答案 0 :(得分:2)

您需要从要解析的数据中删除空的InstallDate结果,然后将属性扩展为@arco444 pointed out。另外,您的循环当前会将解析后的日期分配回循环进行迭代的数组变量,从而破坏了该数组中的所有其他值。

建议使用InvariantCulture代替$null(例如@Moerwald suggested),但不是导致此问题的原因。另一个(性能)优化是使用Contains()字符串方法而不是-match运算符。

这样的事情应该做你想要的:

$reg = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
$culture = [Globalization.CultureInfo]::InvariantCulture

$Soft = Get-ItemProperty $reg
$InstallDate = $Soft |
               Where-Object { $_.InstallDate } |
               Select-Object -Expand InstallDate

for ($i = 0; $i -lt $InstallDate.Length; $i++) {
    if ($InstallDate[$i].Contains('-')) {
        $InstallDate[$i]
    } else {
        $d = [DateTime]::ParseExact($InstallDate[$i], 'yyyyMMdd', $culture)
        $d.ToString('yyyy-MM-dd')
    }
}

也可以进行整个处理:

$reg = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
$culture = [Globalization.CultureInfo]::InvariantCulture

Get-ItemProperty $reg | Where-Object {
    $_.InstallDate
} | Select-Object -Expand InstallDate | ForEach-Object {
    if ($_.Contains('-')) {
        $_
    } else {
        [DateTime]::ParseExact($_, 'yyyyMMdd', $culture).ToString('yyyy-MM-dd')
    }
}

答案 1 :(得分:0)

使用ParseExact时,您需要添加FormatProvider来指定区域性:

$dt = [datetime]::ParseExact("20190319", "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)
$dt.ToString("yyyy-MM-dd")
2019-03-19

ParseExact引发异常,因此$InstallDate无效,因此您可以对其调用ToString。您可以添加其他$null支票:

 $dt = [datetime]::ParseExact("20190319", "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)
 if ($dt) {
   $dt.ToString("yyyy-MM-dd")
 }

希望有帮助