PowerShell DateTime Csv差异

hmae6n7t  于 2023-07-31  发布在  Shell
关注(0)|答案(2)|浏览(85)

我正在导入一个带有日期列的CSV,其格式为“2023-5-29”,我指定$mydate作为参考日期。
我希望返回所有行的日期大于$mydate。

$myfiles  = Import-Csv -Path "C:\pathto\file.csv"
$mydate = ((Get-Date).adddays(-(6+(Get-Date -UFormat %u)))).date
$myfiles | Where-Object {$_.Date -gt $mydate.ToString('MM/dd/yyyy')}

字符串
我的CSV看起来像这样:
x1c 0d1x的数据
当我运行最后一行时,它返回CSV中的每个项目。这是日期时间对象问题吗?是格式化吗?
我没主意了。任何提示都会帮助我。
谢谢你的时间。

kuhbmx9i

kuhbmx9i1#

您需要将Date CSV列中的字符串转换为DateTime示例,而不是将目标日期($mydate)转换为字符串。

$mydate = (Get-Date).AddDays(-13).Date
Import-Csv -Path 'C:\pathto\file.csv' |
    Where-Object {
        $parsed = [datetime]::ParseExact(
            $_.Date,
            'yyyy-M-d',
            [cultureinfo]::InvariantCulture)

        $parsed -gt $mydate
    }

字符串

l2osamch

l2osamch2#

补充Santiago's helpful answer

tl;dr

  • 将引用日期定义为[datetime]示例,而不是 string
    • 将CSV时间戳字符串($_.Date)转换为[datetime],以进行有意义的时间顺序比较。
$myDate = (Get-Date).AddDays(-6+(Get-Date -UFormat %u)).Date
Import-Csv -Path C:\pathto\file.csv |
  Where-Object { [datetime] $_.Date -gt $myDate }

字符串
这依赖于[datetime] '2023-5-29'按预期创建[datetime]示例的事实(字符串'2023-5-29'被正确识别为2023年5月29日)。
请继续阅读以了解背景信息。
为了有意义地按时间顺序对时间戳进行比较/排序,它们必须表示为:

  • 这两种类型都对日期/时间操作提供了丰富的支持。
  • 注意:只有[datetimeoffset]示例与来自不同时区的时间戳进行有意义的比较。
    • :通过 * 字符串格式 * 格式,其 * 词法 * 排序顺序等同于时间顺序*,这特别需要format string,例如:
  • 仅日期:
  • 'yyyy"-"MM"-"dd' [2]
  • 例如'2023-07-02'
  • 对于日期和时间(省略必要的单位,以便进行不太精确的比较):
  • 'yyyy"-"MM"-"dd"T"HH":"mm":"ss"."fffffff'
  • 例如'2023-07-02T12:34:01.2936200'
    *备注
  • 与使用[datetimeoffset]时不同,这种方法**基本上只适用于来自同一时区的时间戳 *;合并时区偏移(例如,-04:00)将 * 不 * 导致词汇顺序也反映时间顺序。
  • 这些格式字符串可以传递给Get-Date-Format参数(例如:Get-Date -Format 'yyyy"-"MM"-"dd')、[datetime][datetimeoffset]示例的.ToString()方法(例如[datetime]::Now.ToString('yyyy"-"MM"-"dd')),或者当使用带有-f运算符的此类示例时(例如'{0:yyyy"-"MM"-"dd}' -f [datetime]::Now
    CSV数据本质上是 * 非类型化的 *,因此当被Import-CsvConvertFrom-Csv解析为[pscustomobject]示例时,总是 * 字符串 * 类型化的[string])[3]
    *使用时间戳的 * 字符串 * 表示只有在CSV列值 * 已经 * 采用其词法顺序等于其时间顺序**的格式时才值得考虑,如上所述。
  • 如果是这样的话,你可以先创建一个引用日期的匹配字符串表示,然后进行字符串比较,因此不需要类型转换,这提供了一个 * 性能优势 *(注意在Where-Object调用中使用了simplified syntax):
# Create the reference timestamp in the same string format as the CSV data
$mydate = (Get-Date).AddDays(-6+(Get-Date -UFormat %u)).Date.ToString('yyyy"-"MM"-"dd')
# Filter using *string* comparison
# Note: Works ONLY with Date column values whose lexical order
#       ordering is equal to its chronological ordering, which does
#       NOT apply to your data.
$myfiles | Where-Object Date -gt $mydate

  • 然而,除非性能是至关重要的,否则仍然值得考虑使用[datetime]转换,特别是如果您还想存储结果示例以供以后进行其他日期/时间操作时-请参阅下一点。
    *否则将列值(timestamp字符串)解析为[datetime]示例
  • 圣地亚哥的回答向您展示了如何通过[datetime]::ParseExact()使用时间戳字符串格式的描述 * 显式地 * 解析时间戳字符串
  • 但是,PowerShell的[datetime]casts(在后台转换为[datetime]::Parse(),其中invariant culture作为文化背景)具有内置的,文化不变的各种格式支持**,包括您的特定格式;也就是说,像[datetime] '2023-5-29'这样的东西按原样工作,并且被正确地识别为2023年5月29日,而不管 * 当前 * 区域性是什么(如$PSCulture中所反映的)。见顶部的解决方案。

[1][datetimeoffset]示例是明确的时间点,具有内置的UTC偏移量(由给定的时区暗示);相同的时间点可以用不同的UTC偏移量表示,[datetimeoffset]可以识别这种等价性-与[datetime]不同,[datetime]的示例要么未指定UTC偏移量(Unspecified.Kind属性值),要么表示 local timestamp(Local),要么以UTC(Utc)表示。只有最后一种是明确的,即使概念上等价的示例,如果它们分别是UtcLocal,也 * 不 * 比较为相等的(但等价的LocalUnspecified可以)。
[2]请注意,在-:.T等字符周围使用了嵌入式引号("...")。这确保了它们在格式化过程中的逐字使用;除了T之外,这些字符在不加引号的情况下是适合区域性的分隔符的占位符。但是,如果显式地指定[cultureinfo]::InvariantCulture作为区域性上下文,则可以 * 不使用 * 嵌入的引号。
[3]GitHub上有两个待处理的特性请求,用于添加类型支持:GitHub issue #11942建议允许通过Import-Csv/ConvertTo-Csv的新-ColumnType参数指定属性类型。GitHub issue #8862建议允许使用Import-Csv/ConvertTo-Csv指定.NET目标类型/自定义PowerShell class(具有强类型属性)

相关问题