【发布时间】:2021-12-01 14:41:00
【问题描述】:
我正在使用带有脚本的 PowerShell 将 .CSV 原始数据文件转换为更易于管理的数据格式,其中包含单独的列、更清晰的视图等。而且由于原始数据的源文件采用美国日期和时间格式(例如 21 年 11 月 23 日下午 1:00),那么如果 PC 采用相同的美国格式,则转换过程运行正常,错误为 0。但是,如果 PC 使用不同的国家/地区日期和时间格式,则 PowerShell 在此过程中会显示红色错误。
当 PC 采用其他 DateTime 格式时,我看到的主要错误是:
“使用“1”个参数解析:“字符串未被识别为有效的日期时间。”
问题是将使用它的 PC 不是美国格式(仅更改为美国格式进行测试),所以这里有人可以帮我在转换过程中添加语法或句子以简单直接在代码中指定一个固定格式,该格式独立于 PC 时钟日期和时间格式保持静态输出格式,如果文件的输入之一是“11/23/21, 1:00 PM”,则在您希望以“dd-MMM-yyyy hh:mm”格式输出的代码具有类似“23-Nov-2021 01:00 PM”的结果
用于转换的脚本中的代码部分是:
…
$data = $csvData | ? {$_ -match "\(DTRE"}
dtreFileData = New-Object System.Collections.Generic.List[PSCustomObject]
foreach ($item in $data)
{
$null = $item.Strategy -match "\(DTRE\|(.*)\)"
$v = $Matches[1] -split '\|'
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$dtreData = [PSCustomObject]@{
'DateTime' = ([datetime]::Parse($item.'Date/Time'))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
}
$null = $dtreFileData.Add($dtreData)
$null = $dtreAllData.Add($dtreData)
}
$dtreFileData | Export-Csv -Path (Join-Path (Split-Path -Path $f -Parent) ($outFile + '.csv')) -Force -NoTypeInformation -Encoding ASCII
…
原始源数据示例(在 CVS 文件中有几十行类似下一行):
...(DTRE|49.0|48.2);...;11/23/21, 12:58 PM...;
...(DTRE|52.1|52.0);...;11/23/21, 1:00 PM...;
...
...
输出看起来像:
我尝试使用此处 (stackoverflow.com) 的其他帖子中的 DateTime 示例来调整代码以在没有美国日期和时间格式的 PC 中工作,并获得上述 DateTime 格式结果。例如:
'DateTime' = ([datetime]::Parse($item.'yyyy-MM-dd:HH:mm:ss'))
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss'))
…
$culture = [Globalization.CultureInfo]::InvariantCulture
…
'DateTime' = ([datetime]::ParseExact($item.'yyyy-MM-dd:HH:mm:ss', $culture))
…
但是对于这些示例,PowerShell 显示错误“无法将参数绑定到参数 'InputObject',因为它为空”
@Seth 回答后更新:
尝试下一次修改代码时,PC 系统日期格式为“24-Nov-21”,其余如上:
…
$resultvalue = $v[0] | Convert-CurrencyStringToDecimal
$expectedvalue = $v[1] | Convert-CurrencyStringToDecimal
$cultureInfo= New-Object System.Globalization.CultureInfo("es-ES")
$dtreData = [PSCustomObject]@{
'DateTime' = ([System.DateTime]::Parse($item.'Date/Time', $cultureInfo))
'ResultValue' = [decimal]$resultvalue
'ExpectedValue' = [decimal]$expectedvalue
…
【问题讨论】:
-
CSV 文件应该有一个规范,明确显示日期和时间的格式。使用 ISO-8601 是个好主意。目前尚不清楚问题中的
$item是什么。([datetime]::ParseExact('2021-11-01', 'yyyy-MM-dd', $null))有效。在问题中显示一些示例日期会很有帮助。 -
谢谢@lit。我更新了显示 3 次
$item进入脚本文件的帖子。我尝试使用'DateTime' = ([datetime]::Parse($item.'yyyy-MM-dd')),但 PowerShell 给出错误:“Export-Csv:无法将参数绑定到参数 'InputObject',因为它为空。” 我不知道是否可能是 @987654334 的部分@ 可能导致格式问题,但我尝试将其更改为-Encoding BigEndianUnicode和-Encoding UTF32以及同样的错误。我还展示了“原始数据”中的格式以及转换后的外观,但问题是我不使用美国格式。 -
请注意,当 PC 日历/时钟为美国格式时,脚本可以完美运行,进行完美转换,除了因为它以美国格式显示日期,月份在首位。当 PC 是另一种日历/时钟格式时,转换问题就出现了,这正是需要使用脚本的情况。所以我需要的是一种“通用”方式,我可以在代码中指定将每个 DateTime 项转换为特定格式,例如
dd-MMM-yyyy hh:mm(23-Nov-2021 01:00 PM)。一种通用且固定的方式,无论 PC 中的日期和时间格式如何。 -
对这种情况最直接的解决方案是控制创建 CSV 数据的过程。它必须始终以特定格式创建它。使用
yyyy-MM-DD作为日期。总是。如果您无法控制 CSV 数据的创建,那么您可以为您的阅读脚本指定一个参数来指示日期格式。您还可以对几种格式使用 try/catch 来查看其中一种是否有效,但这并不可靠。解决方案是更正 CSV 数据的创建。 -
感谢您的评论@lit。代码不是我创建的,我不知道您是否说要修改最后一行:
$dtreFileData | Export-Csv -Path (Join-Path (Split-Path -Path $f -Parent) ($outFile + '.csv')) -Force -NoTypeInformation -Encoding ASCII可能会更改-Encoding ASCII。我尝试将ASCII更改为其他人,但当我这样做时 PowerShell 会出错。您能否将您的解决方案作为答案显示您的意思是什么?需要添加什么以及需要修改什么。您可以获取代码并执行所需的操作来展示操作方法。
标签: powershell datetime