Как я могу принимать произвольно отформатированные даты в PowerShell - PullRequest
1 голос
/ 20 февраля 2020

У меня есть файл журнала входа в систему, который объединяет несколько источников. Источники (а их много) используют различные форматы дат. Я использую полученный объект $ objList для передачи их в SQL базу данных. Когда я пытаюсь затем использовать SQL Запросы, я пропускаю данные.

Вот небольшой фрагмент необработанного ввода с сентября 2007 года:

  1. Вход в систему; Имя пользователя; Server01 ; 10/09/2007 09: 56: 40
  2. Вход в систему; Имя пользователя; Server02; 10/09/2007 11: 26: 20
  3. Вход в систему; Имя пользователя; Server03; 9/11/2007 10:16:27
  4. Вход в систему; Имя пользователя; Server04; 11/09/2007 12: 28: 45

Обратите внимание, что третий - американский формат, остальные - европейский. Мне нужен способ заставить эти вещи встраиваться в сценарий в согласованном формате даты. В этом файле буквально сотни тысяч строк, поэтому он не может c до go вручную и ничего модифицировать.

Вот то, что у меня есть до сих пор.

  IF ($SplitUsr.Count -eq '4')
    {
        $varAction = $SplitUsr[0]
        IF ($varAction -eq 'Logon')
        {
            $varActionx = $SplitUsr[0].Trim()
            $varUser = $SplitUsr[1].Trim()
            $varHostname = $SplitUsr[2].Trim()
            $varTime = $SplitUsr[3].Trim()

            try {$datetime = [dateTime]::Parse("$varTime",([Globalization.CultureInfo]::CreateSpecificCulture('en-GB')))}
            catch [System.Management.Automation.MethodInvocationException]
            {
                $datetime = [dateTime]::Parse("$varTime",([Globalization.CultureInfo]::CreateSpecificCulture('en-US')))
            }

                $objLogon = New-Object PSObject
                $objLogon | Add-Member -Membertype NoteProperty -Name "Entry" -Value $intCount
                $objLogon | Add-Member -Membertype NoteProperty -Name "Logon" -Value '1'
                $objLogon | Add-Member -Membertype NoteProperty -Name "User" -Value $varUser
                $objLogon | Add-Member -Membertype NoteProperty -Name "Hostname" -Value $varHostname
                $objLogon | Add-Member -Membertype NoteProperty -Name "Date" -Value $datetime
                $objList += $objLogon

К сожалению, это анализирует их в

  1. 10 сентября 2007 г. 09:56:40
  2. 10 сентября 2007 г. 11:26:20
  3. 09 ноября 2007 г. 10:16:27
  4. 11 сентября 2007 г. 12: 28: 45

Вы можете видеть, что третий пример, с американским форматированием в Необработанные данные вышли как ноябрь вместо 11 сентября (инвертируя 9 и 11).

То же самое происходит повсюду. Когда я смотрю на SQL записи за декабрь, вот что я получаю:

  1. 07 декабря 2007 г. 09: 53: 33
  2. 07 декабря 2007 г. 11:37:48
  3. 12 июля 2007 г. 13: 25: 02
  4. 07 декабря 2007 г. 13: 26: 38
  5. 07 декабря 2007 г. 15: 04: 56

Вы можете видеть, что третий каким-то образом перевернул 12 и 7. Это проблема, которую я пытаюсь решить.

Есть предложения?

Редактировать: еще несколько примеров:

  1. Вход в систему; Имя пользователя; Server01; 18/11/2008 11: 19: 08
  2. Вход в систему; Имя пользователя; Server02; 18/11/2008 11:21:46
  3. Вход в систему; Имя пользователя; Server03; 18/11/2008 14: 28: 30
  4. Вход в систему; Имя пользователя; Server04; 19/11/2008 09: 55: 50
  5. Вход в систему; Имя пользователя; Имя_сервера; 19/11/2008 14: 14: 09
  6. Вход в систему; Имя пользователя; Имя_сервера; 19/11/2008 14: 19: 56
  7. Logon; Имя пользователя; Servername; 20/11/2008 12:19:57 PM

Не все AM / PM указывают на американское форматирование, к сожалению.

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Это «КИ», о котором вы говорили:

$dates = @( '10/09/2007 09:56:40',
            '09/10/2007 11:26:20',
            '10/09/2007 10:16:27 AM',
            '10/09/2007 12:28:45' )

    $cultureUS = [CultureInfo]::CreateSpecificCulture("en-US")
    $cultureEU = [CultureInfo]::CreateSpecificCulture("en-GB")

    $maxDays   = 2  # Max. allowed difference between current date and former date in days

    for( $i = 0; $i -lt $dates.Count; $i++ ) {

        $currentDate = [DateTime]::Parse( $dates[ $i ],$cultureEU )

        if( $i -gt 0 ) {
            $diffPast = New-TimeSpan -Start $lastDate -End $currentDate
        }
        else {
            $diffPast = New-TimeSpan -Start $currentDate -End $currentDate
        }

        if( $diffPast.Days -gt $maxDays ) {

            # check if month of current date is day of last date => culture issue
            if( $currentDate.Day -eq $lastDate.Month -or $currentDate.Month -eq $lastDate.Day ) {
                $currentDate = [DateTime]::Parse( $dates[ $i ],$cultureUS )
            }
        }

        $currentDate

        $lastDate = $currentDate

    }
0 голосов
/ 21 февраля 2020

К сожалению, не все AM / PM указывают американские форматы даты.

Без дополнительной информации вы не сможете решить вашу проблему из-за присущих ей неясностей:

9/11/2007 10:16:27 AM

Невозможно определить, является ли это отметкой времени en-US (США), относящейся к 11-му дню сентября (первый месяц), или отметкой времени en-GB (Великобритания), относящейся к девятому день ноября (первый день).

Только если первый или второй компонент имеет значение 13 или выше en-US или en-GB подразумевается , и только такие временные метки будут правильно обрабатываться try / catch logi c в вашем вопросе.


Если вы предоставите дополнительное ограничение, что все даты должны встретить, решение возможно.

Например, если вы знаете, что все даты попадают в данный месяц :

# The month that all log entries are expected to fall into:
$refMonth = 9  # September, for example.

# Create an array of the cultures to use for parsing:
[cultureinfo[]] $cultures = 'en-GB', 'en-US'

'11/9/2007 17:02:15',
'9/11/2007 05:02:44 PM',
'11/9/2007 05:03:01 PM' | ForEach-Object {

   $ok = $false; [datetime] $dt = 0
   foreach ($culture in $cultures) {
     $ok = [datetime]::TryParse($_, $culture, 'None', [ref] $dt) -and $dt.Month -eq $refMonth
     if ($ok) { break }
   }
   if (-not $ok) { Write-Error "Not recognized as a date in the expected month: $_" }
   else { $date } # Output the resulting date.

}

Выше приведено следующие, показывая, что все даты были проанализированы как месяц 9 (сентябрь) даты :

Tuesday, September 11, 2007 5:02:15 PM
Tuesday, September 11, 2007 5:02:44 PM
Tuesday, September 11, 2007 5:03:01 PM
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...