【问题标题】:Parse string to datetime format将字符串解析为日期时间格式
【发布时间】:2019-09-14 17:00:15
【问题描述】:

我将所有已安装的软件安装到我的计算机上,并将结果打印到 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) 或者它们为空/null,执行脚本后我得到以下结果:

安装日期 ------------ 2019-04-01

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

找不到“ParseExact”和参数计数的重载:“3”。 在 C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:12 char:9 + $InstallDate = [日期时间]::ParseExact($InstallDate[$i], 'yyyy ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest 找不到“ToString”的重载和参数计数:“1”。 在 C:\Users\xxx\Desktop\xxx\ForLoopTest.ps1:13 char:9 + $InstallDate.ToString('yyyy-MM-dd') + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest

【问题讨论】:

  • 使用:$InstallDate = $Soft | Select-Object -ExpandProperty InstallDate;
  • 之后我得到Select-Object : Property "InstallDate" cannot be found.
  • 是的,但仅适用于属性不存在的对象。无论如何,您将无法解析它们。你的$installDate 变量应该有一个字符串列表,其中属性 did 存在
  • 好的,但它只打印日期,格式为 yyyy-MM-dd。安装日期为空的对象很少,但是yyyyMMdd格式的对象,它们不打印。

标签: powershell


【解决方案1】:

您需要从正在解析的数据中删除空的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')
    }
}

【讨论】:

    【解决方案2】:

    使用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")
     }
    

    希望有帮助

    【讨论】:

    • 我试过这个。这可以像在您的示例中那样手动添加日期,但如果我有 $InstallDate[$i] 则无法正常工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多