PowerShell arquivo CSV erros de conversão devido PC com diferente formato de data / hora que o arquivo de entrada

0

Pergunta

Eu estou usando o PowerShell com um script para converter um .CSV matérias arquivo de dados em mais gerenciável formato de dados com colunas separadas, uma visão mais limpa, etc. E porque o arquivo de origem com os dados brutos, está em NÓS, formato de data e hora (e.g. 11/23/21, 1:00 PM) e, em seguida, se o PC estiver no mesmo formato US o processo de conversão é executado perfeitamente como deveria com 0 erros. MAS, se o PC está em um país diferente formato de data e hora e, em seguida, PowerShell mostra erros em vermelho no processo.

Quando o PC está em outro formato de data / hora que eu vejo o principal erro é:

"Analisar" com "1" argumento(s): "String não foi reconhecida como DateTime válido."

E o problema é o PC onde esta vai ser usado não está em NÓS formato (alterado somente para NÓS formato para testes), assim poderia alguém aqui, por favor, ajude-me a acrescentar para o processo de conversão sintaxe ou frase/s simplesmente especificar diretamente o código de um formato fixo que mantém um estática formato de saída de forma independente sobre o relógio do computador do formato de data e hora, e se uma das entradas para o arquivo é "11/23/21, 1:00", em seguida, especificar o código que você deseja que a saída no formato "dd-MMM-aaaa hh:mm" para ter um resultado como "23-Nov-2021 01:00 PM"

A seção de código no script utilizado para a conversão é:

…
$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
…

Exemplo de matérias de origem de dados (no CVS do arquivo são dezenas de linhas como o próximo):

...(DTRE|49.0|48.2);...;11/23/21, 12:58 PM...;

...(DTRE|52.1|52.0);...;11/23/21, 1:00 PM...;

...

...

E a Saída parece:

enter image description here

Eu tentei com DateTime exemplos em outros posts aqui (stackoverflow.com) para ajustar o código para trabalhar em um PC, sem NÓS, formato de data e hora e, para obter o formato de data / hora resultado descrito acima. Exemplos como:

'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))
…

Mas com esses exemplos PowerShell mostra o erro "não é Possível vincular o argumento para o parâmetro 'InputObject' porque ele é nulo"

Atualização após a resposta do @Seth:

Ao tentar avançar a modificação do código, com o PC formato de data do sistema em "24-Nov-21" e deixando o resto como acima:

…
$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
…

em seguida, o PowerShell mostra o seguinte erro: enter image description here

datetime powershell
2021-11-23 21:14:34
1

Melhor resposta

1

Como foi explicado, é uma boa idéia para corrigir o CSV para ter uma melhor dateformat. Um exemplo seria a norma ISO 8601, que pode ser usado com Get-Date -Format "o".

O que disse Get-Date depende de C# coisas no plano de fundo. Assim, você pode usar código C# para ler que, em uma determinada cultura. Como você sabe a origem da cultura isso deve funcionar. A fixação do carimbo de data / hora é ainda uma idéia melhor.

$cultureInfo= New-Object System.Globalization.CultureInfo("en-US")
$dateString = "11/23/21, 12:58 PM";
$dateTime = [System.DateTime]::Parse($dateString, $cultureInfo);
Get-Date -Format "o" $dateTime

Com este código de exemplo que você gostaria de atribuir $dateString o valor de $item.' Date/Time' e o resultado é provável que queira seria o resultado de Get-Date. Então você poderia atribuir $dtreData.'DateTime' o resultado de que Get-Date chamada. Como alternativa é possível utilizar o .NET Objeto DateTime para converter diretamente a uma cultura particular. Por exemplo, chamando $dateTime.ToString((New-Object System.Globalization.CultureInfo("en-ES"))). Apesar de não ser de todo útil que você também poderia passar o identificador de formato para esse método. Isso pode ser relevante se você quiser evitar a criação de objetos adicionais. Um pouco de chamada desnecessária seria $dateTime.ToString("o", (New-Object System.Globalization.CultureInfo("en-ES"))) (como o formato é o mesmo em todas as culturas).

2021-12-01 06:41:00

Obrigado pela sua resposta @Seth, mas nenhuma solução ainda. Eu tentei modificar o código com as suas linhas, mas eu ainda sou incapaz de obter a data e hora em um formato especificado diretamente no código, dizendo: "tome cada valor de data / hora no arquivo CSV arquivo de entrada e convertê-los para o formato dd-MMM-yyyy hh:mmou, por exemplo, o nome de cultura es-ES, ou algo semelhante", isto é, a ser especificada diretamente no código, como um universal/forma genérica, onde este funciona independentemente se o PC está em inglês, formato de data e hora, ou se o PC está em espanhol, formato de data e hora, ou se o PC está em francês, formato de data e hora
adiario

Com suas linhas, eu tentei o seguinte modificação do código, com o PC data do sistema no formato US: $resultvalue = $v[0] | Convert-CurrencyStringToDecimal $expectedvalue = $v[1] | Convert-CurrencyStringToDecimal $cultureInfo= New-Object System.Globalization.CultureInfo("en-US") $dtreData = [PSCustomObject]@{ 'DateTime' = ([System.DateTime]::Parse($item.'Date/Time', $cultureInfo)) 'ResultValue' = [decimal]$resultvalue 'ExpectedValue' = [decimal]$expectedvalue } e a conversão funciona sem erros, mas de dar o resultado no formato US & ser dependente do sistema operacional formato da data.
adiario

Eu também tentei fazer a seguinte modificação do código, com o PC formato de data do sistema em "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 e aqui PowerShell dá erros dizendo: "Export-Csv : não é Possível vincular o argumento para o parâmetro 'InputObject' porque ele é nulo"
adiario

Sobre Get-Date -Format "o" $dateTime Eu realmente não sei de onde seria o seu lugar no código postado em questão. Eu tentei colocar ele em vários lugares como na última linha, ou depois de 'DateTime' = ([System.DateTime]::Parse($item.'Date/Time', $cultureInfo))ou para ele, mas PowerShell dá erros. Sobre $dateString = "11/23/21, 12:58 PM"; Eu não uso essa parte porque eu ver, seria um exemplo de entrada e, neste caso, a entrada de valores de DateTime já estão no arquivo CSV que são os valores que precisam ser trabalhadas.
adiario

No caso de você saber como @Seth, por favor, você poderia modificar o código postado na pergunta acima e adicione-as modificações necessárias para ter o resultado que eu preciso para a data e a hora. Muito obrigado pelo seu tempo!
adiario

Você está criando um objeto datetime com uma cultura específica. Você quer que seu $dtreData para ser Get-Date -Format "o" $dateTime. Um Get-Date usando $dateTime como entrada também deve usar o seu regular localidade. Como alternativa, você pode definir explicitamente a localidade para a saída e.g. usando $localDT.ToString((New-Object System.Globalization.CultureInfo("en-ES"))).
Seth

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................