Powershell - 将日期与 CSV 日期进行比较

Powershell - compare date with CSV date

我正在尝试将输入的日期与 CSV 中的日期进行比较,如果输入的日期早于 CSV 中的日期,则显示一条消息。

我遇到了困难,不确定是否需要将 CSV 中的日期从字符串转换为正确比较日期。

代码已经到此为止:

$CSV=Import-Csv C:\Users\person\Desktop\date.csv 
$InputDate = Get-Date -Format "MM/dd/yyyy" (Read-Host -Prompt 'Enter the date')
$CreatedDate = Get-Date -Format "MM/dd/yyyy HH:mm" $CSV.updated

if($InputDate -gt $CreatedDate) {
  write-host "Input Newer"
}
else {
  write-host "Input Older"
}

比较似乎不正确。

CSV 格式如下(包含单行,因此可以假定 $CSV.updated 包含 单个 日期字符串):

updated
11/07/2016 16:14

您需要将字符串中的日期解析为日期时间类型以进行日期比较。

$CSV = Import-Csv C:\Users\person\Desktop\date.csv 
$InputDate = [datetime]::Parse( $(Read-Host -Prompt 'Enter the date (MM/dd/yyyy)') )
$CreatedDate = [datetime]::Parse( $CSV.updated )
if($InputDate -gt $CreatedDate)
{write-host "Input Newer"}
else
{write-host "Input Older"}

提供了一个有效的解决方案;让我更清楚地说明问题是什么:

  • 您似乎希望-Format "MM/dd/yyyy"指定输入解析格式;事实上,它格式化 output,然后变成 [string].

    • 但是,为了进行有意义的日期比较,您需要一个 [datetime] 实例。
  • 您对(隐含的)-Date 参数((Read-Host ...)$csv.updated)的参数被隐含 解析,基于当前文化 (System.Globalization.CultureInfo.CurrentCulture) 认可的标准格式。

因此:

  • 如果 隐式 解析已经正确识别了您的论点(正如您接受 Kiran 的回答所暗示的那样),解决方案是简单地 从您的代码中删除 -Format 个参数

      # Parse each input string implicitly, based on the current culture,
      # and output a [datetime] instance, which will compare as expected
      # with `-gt`
      $InputDate = Get-Date (Read-Host -Prompt 'Enter the date')
      $CreatedDate = Get-Date $CSV.updated
    
  • 相反,如果您确实需要通过 "MM/dd/yyyy" 格式字符串显式解析以便识别您的参数,请调用 .NET 方法 [datetime]::ParseExact(<string>, <format>[, <culture>]) (System.DateTime.ParseExact);例如:

      # Note: The input string must match the format *exactly*
      $InputDate = [datetime]::ParseExact(
        (Read-Host -Prompt 'Enter the date'), # input string
        "MM/dd/yyyy", # format string
        $null  # default to the current culture's rules
      ) 
    

继续阅读以了解背景信息。


Get-Date 输入和输出格式和数据类型:

-Format "MM/dd/yyyy" 没有指定 input 解析格式,它指定 output 字符串-格式化 format,这有两个含义:

  • String 输入传递给输入参数 -Date(第一个 positional 参数绑定到) 被隐式 解析[datetime],基于 标准 当前文化[1]识别的字符串格式;实际上,在幕后调用了以下内容:

      [datetime]::Parse((Read-Host -Prompt 'Enter the date'), [cultureinfo]::CurrentCulture)
    
    • (在上面的调用中省略 [cultureinfo]::CurrentCulture 具有相同的效果。)
    • 警告当你转换一个字符串到[datetime]时,它是 不变 文化([cultureinfo]::InvariantCulture,基于美式英语),PowerShell 经常这样做是为了代码的稳定性文化;诸如 Get-Date 之类的 cmdlet 是 not 文化不变的是一个历史事故,由于担心破坏旧代码而不会得到纠正;背景见 this GitHub issue。例如,文化 fr-FR(法语)生效,[datetime] '12/1] 产生 12 月 1 日 (第一个月),而 Get-Date -Date '12/1' 产生 1月12日(第一天)。
  • Get-Date命令将return一个(格式化的)字符串而不是[datetime]实例;也就是说,根据 current 文化的规则,根据传递给 -Format 的格式字符串对输入隐式解析的 [datetime] 实例进行格式化;如果 $dt 包含一个 [datetime] 实例,-Format "MM/dd/yyyy" 等同于 (请注意直接调用 System.DateTime.ToString() 如何为您提供选项指定 不同的 文化,而 -Format 没有):

      $dt.ToString("MM/dd/yyyy", [cultureinfo]::CurrentCulture)
    

(从 PowerShell v7.0 开始),Get-Date cmdlet 支持为 指定格式字符串输入解析.

  • 如上所述,根据 标准 date/time 格式当前文化 识别。

  • 您必须直接调用 .NET 方法 [datetime]::ParseExact(<string>, <format>[, <culture>]) (System.DateTime.ParseExact),如上一节所示。

  • 一旦你有一个 [datetime] 实例,你可以将它(通过 -Date)传递给 Get-Date -Format 以获得 [=155] 的格式化字符串表示=]当前文化;或者,您可以直接在实例上调用 .ToString(<format>[, <culture>]) (System.DateTime.ToString),这样您还可以选择针对 不同文化 .

    进行格式化

至于Get-Date输入输出数据类型:

从根本上说,输入 的传递方式(特定参数)决定了结果 [datetime] 实例的解释方式,具体取决于 cmdlet 的方式选择实例的 .Kind 属性 值(UtcLocalUnspecified)。

.Kind 属性 值决定了 [datetime] 实例代表的特定全局时间点(如果有)。 .Kind 值也会影响实例的字符串表示,具体取决于应用的特定格式(特别是包含时区信息)。

生成的 [datetime] 实例是:

  • 或者:输出直接(默认)
  • 或:如果传递了 -Format 参数,是派生请求的 字符串表示的基础 ([string]).

Get-Date 确定 .Kind 属性 值如下:

  • 没有 -Date参数,你得到一个Local实例(代表当前时间点)

    • (除非字符串被传递给-Date),使用各种偏移参数,例如-Year-Day,也会生成一个 Local 实例。
  • 对于 -Date 已经 类型 [datetime] 的参数,该实例按原样使用,这意味着保留现有 .Kind 属性 值。

  • 使用 string -Date 参数(隐式解析),.Kind 值将是 Unspecified (表示一个抽象的时间点,不参考具体时区),包括如果结合-Year.

    等参数
  • A numeric -Date 参数(例如,637165787436900010)被解释为 System.DateTime.Ticks 值,这也生成一个 Unspecified 实例。

注意:PowerShell [Core] 7.1 将引入一个 -AsUTC 开关,使输出/待格式化的实例成为 Utc 类型; -AsLocal-AsUnspecified 开关(and/or 和 -AsKind <kind> 参数)也在讨论中 - 请参阅 this GitHub issue


[1] 如果输入已经是 [datetime] 实例,则按原样使用。