Powershell - сравнить дату с датой CSV - PullRequest
1 голос
/ 06 февраля 2020

Я пытаюсь сравнить введенную дату с датой из 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

Ответы [ 2 ]

2 голосов
/ 06 февраля 2020

Для сравнения дат вам нужно проанализировать дату в строке в тип datetime.

$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"}
0 голосов
/ 06 февраля 2020

Ответ Кирана Патнаюкуни обеспечивает эффективное решение; позвольте мне прояснить, в чем проблема:

  • Вы, казалось бы, ожидали -Format "MM/dd/yyyy", чтобы указать формат разбора ввода ; фактически он форматирует вывод , который затем становится [string].

    • Однако для значимого сравнения дат необходим экземпляр [datetime].
  • Ваши аргументы для (подразумеваемого) параметра -Date ((Read-Host ...), $csv.updated) были неявно проанализированы на основе стандартных форматов, распознаваемых текущая культура (System.Globalization.CultureInfo.CurrentCulture).

Поэтому:

  • Если ваши аргументы уже правильно распознаются неявным синтаксическим анализом (как вы предполагаете, принимая ответ Кирана), решение состоит в том, чтобы просто удалить -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" не определяет формат ввода , он определяет формат output форматирования строки , который имеет два значения:

  • String входные данные, переданные во входной параметр -Date (с которым связан первый позиционный аргумент) - неявно проанализировано как [datetime], на основе стандарта форматов строк, распознаваемых текущей культурой [1] ; в действительности за кадром вызывается следующее:

    [datetime]::Parse((Read-Host -Prompt 'Enter the date'), [cultureinfo]::CurrentCulture)
    
    • (пропуск [cultureinfo]::CurrentCulture в приведенном выше вызове имеет тот же эффект.)
    • Предупреждение : Когда вы приводите строку к [datetime], это инвариант культура ([cultureinfo]::InvariantCulture, основано на US-Engli sh) применяется , что часто делает PowerShell для стабильности кода в разных культурах; что командлет, такой как Get-Date, является , а не культурно-инвариантным, является исторической случайностью, которая не будет исправлена ​​из-за боязни взлома старого кода; см. этот выпуск GitHub для фона. Например, при действующей культуре fr-FR (по-французски) [datetime] '12/1] дает 1 декабря (месяц первый), тогда как Get-Date -Date '12/1' дает 12 января (день первый).
  • Команда Get-Date вернет (отформатированную) строку вместо [datetime] instance ; то есть экземпляр [datetime], неявно анализируемый при вводе, форматируется на основе строки формата, переданной в -Format, на основе правил культуры current ; если $dt содержит [datetime] экземпляр, -Format "MM/dd/yyyy" эквивалентен (обратите внимание, что прямой вызов System.DateTime.ToString() дает вам возможность указать другая культура, которую -Format не имеет):

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

(по состоянию на PowerShell v7.0), Get-Date командлет имеет нет поддержку для указания строки формата для input синтаксического анализа.

  • Как указано, передача строки в -Date приводит к неявному синтаксическому анализу на основе стандартных форматов даты / времени , распознаваемых современной культурой .

  • Вам придется вызвать. NET метод [datetime]::ParseExact(<string>, <format>[, <culture>]) (System.DateTime.ParseExact) , как показано в верхней части.

  • Если у вас есть экземпляр [datetime], вы можете передать его (через -Date) в Get-Date -Format, чтобы получить форматированное строковое представление для текущей культуры ; Кроме того, вы можете вызвать .ToString(<format>[, <culture>]) (System.DateTime.ToString) непосредственно в экземпляре, что также дает вам возможность форматировать для другой культуры .

Что касается Get-Date ввода и вывода типов данных :

По сути, как ввод передается (уточняется c arguments) определяет способ интерпретации результирующего экземпляра [datetime] на основе того, как командлет выбирает значение свойства .Kind экземпляра (Utc, Local или Unspecified) .

Значение свойства .Kind определяет, какой конкретный c глобальный момент времени, если таковой имеется, представляет экземпляр [datetime]. Значение .Kind также может влиять на строковое представление экземпляра, в зависимости от того, какое заданное форматирование c применяется (в частности, включение информации о часовом поясе).

В результате получается экземпляр [datetime]:

  • либо: вывести напрямую (по умолчанию)
  • , либо: если передан аргумент -Format, является основой для получения запрошенного строкового представления ([string]).

Get-Date определяет значение свойства .Kind следующим образом:

  • С нет -Date аргумент, вы получаете экземпляр Local (представляющий текущую точку во времени)

    • (Если строка не также передана -Date), используя различные параметры смещения, такие как -Year и -Day, также создают экземпляр Local.
  • с аргументом -Date, который уже имеет значение типа [datetime], этот экземпляр используется как есть, что означает, что существующее значение свойства .Kind сохраняется.

  • С аргументом string -Date (который анализируется неявно) значение .Kind будет Unspecified (представляющим abstract момент времени, без ссылки на определенный c часовой пояс), в том числе в сочетании с такими параметрами, как -Year.

  • A цифра c* Аргумент 1296 * -Date (например, 637165787436900010) интерпретируется как значение System.DateTime.Ticks, которое также создает экземпляр Unspecified.

Примечание : PowerShell [Core] 7.0 представит переключатель -AsUtc, который придает экземпляру, отформатированному в формате string / to-be-string, вид Utc; Также обсуждаются переключатели -AsLocal и -AsUnspecified (и / или параметр -AsKind <kind>) - см. этот выпуск GitHub .


[1] Если вход уже является экземпляром [datetime], он используется как есть.

...