如何在PowerShell中接收随机格式的日期

如何在PowerShell中接收随机格式的日期,powershell,formatting,Powershell,Formatting,我有一个登录跟踪日志文件,它是多个源的合并。这些数据源(有很多)使用多种日期格式。我正在使用生成的$objList对象将它们移交给SQL数据库。当我尝试使用SQL查询时,我丢失了数据 以下是2007年9月的一小部分原始输入: 登录;用户名;Server01;10/09/2007 09:56:40 登录;用户名;Server02;10/09/2007 11:26:20 登录;用户名;服务器03;2007年9月11日上午10:16:27 登录;用户名;服务器04;11/09/2007 12:28:4

我有一个登录跟踪日志文件,它是多个源的合并。这些数据源(有很多)使用多种日期格式。我正在使用生成的$objList对象将它们移交给SQL数据库。当我尝试使用SQL查询时,我丢失了数据

以下是2007年9月的一小部分原始输入:

  • 登录;用户名;Server01;10/09/2007 09:56:40
  • 登录;用户名;Server02;10/09/2007 11:26:20
  • 登录;用户名;服务器03;2007年9月11日上午10:16:27
  • 登录;用户名;服务器04;11/09/2007 12:28:45
  • 请注意,第三个是美国格式,其他是欧洲格式。我需要一种方法将这些内容以一致的日期格式吸收到脚本中。这个文件中有成百上千行,所以手工修改任何内容是不现实的

    这是我到目前为止所拥有的

      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
    
    不幸的是,这将它们解析为

  • 2007年9月10日09:56:40
  • 2007年9月10日11:26:20
  • 2007年11月9日10:16:27
  • 2007年9月11日12:28:45
  • 您可以看到第三个示例,即原始数据中带有美国格式的示例,显示为11月,而不是9月11日(将9和11颠倒)

    同样的事情正在各地发生。当我查看12月份的SQL条目时,我得到的是:

  • 2007年12月7日09:53:33
  • 2007年12月7日11:37:48
  • 2007年7月12日13:25:02
  • 2007年12月7日13:26:38
  • 2007年12月7日15:04:56
  • 你可以看到第三个以某种方式把12和7倒过来了。这就是我试图解决的问题

    有什么建议吗

    编辑:更多示例:

  • 登录;用户名;Server01;18/11/2008 11:19:08
  • 登录;用户名;Server02;18/11/2008 11:21:46上午
  • 登录;用户名;服务器03;18/11/2008 14:28:30
  • 登录;用户名;服务器04;19/11/2008 09:55:50
  • 登录;用户名;服务器名;19/11/2008 14:14:09
  • 登录;用户名;服务器名;19/11/2008 14:19:56
  • 登录;用户名;服务器名;20/11/2008 12:19:57下午
  • 不幸的是,并非所有的AM/PM都表示美国格式

    这就是你所说的“KI”:

    $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
    
        }
    
    不幸的是,并非所有的AM/PM都表示美国日期格式

    没有其他信息,您无法解决问题,因为固有的模糊性:

    9/11/2007 10:16:27 AM
    
    无法判断这是指9月11日(第一个月)的
    en-US
    (美国)时间戳,还是指11月9日(第一天)的
    en-GB
    (英国)时间戳

    只有当第一个或第二个组件恰好为
    13
    或更高时,才会隐含
    en-US
    en-GB
    ,并且只有这样的时间戳才会被问题中的
    try
    /
    catch
    逻辑正确处理


    如果您提供了所有日期都必须满足的附加约束,则可以找到解决方案。

    例如,如果您知道所有日期都属于给定的月份:

    上述结果表明,所有日期都被解析为月份
    9
    (9月)日期:

    2007年9月11日星期二下午5:02:15 2007年9月11日星期二下午5:02:44 2007年9月11日星期二下午5:03:01
    使用
    [datetime]::tryparse
    方法可能会更幸运。而且,您的示例没有跟踪。你在最后说“你可以看到”关于得到12&7反转,但我看不到,因为你没有发布任何与错误对应的原始数据让我追溯它。你的一小部分原始数据来自9月,但你的“明显”例子来自7月或12月。请阅读创建一个好的例子,看看你是否能编辑你的文章。我发布的第一个例子也是不正确的。在九月输出的中间有一个十一月,它是9和11倒置的。我只添加了七月和十二月的例子,因为它们在视觉上更加突出,因为单词本身的长度不同。为了让这一点更清楚,我要重申一下。为了使这一点起作用,你必须查看你的数据,并制定一套始终有效的规则。如果它看起来像这样,那么就这样解释它。如果它看起来像另一件事,那么用另一种方式来解释它。因为您可以访问完整的列表,所以您更有可能找出一组有效的规则。一旦你这样做了,为每种类型的数据写一个转换器,你就得到了答案。我希望你能明白这一点。请允许我给你给新来者的标准建议:如果一个答案解决了你的问题,请点击大复选标记(✓) 在它旁边,也可以选择向上投票(向上投票需要至少15个信誉点)。如果您发现其他答案有帮助,请向上投票。接受(为此您将获得2个信誉点)向上投票有助于未来的读者。如果您的问题还没有完全回答,请提供反馈或。我尝试了一下。不幸的是,并非所有的AM/PM都表示美国日期格式。我从尝试中发现了一些。我将它们添加到了原始帖子中。@RickRDR如果不是所有的AM/PM都是美国格式,那么如果2020年1月2日是2月1日,程序怎么知道呢是一月二日还是一月二日?@f6a4这正是我希望在这里得到的答案。我所知道的是,对于一个人来说,有一大串的台词是显而易见的(例如)12月,无论日期是以何种方式编写的。我希望得到一些逻辑,可以帮助我通过PoSh以编程方式执行同样的操作。请重试。此脚本检查前一个日期是否接近当前日期。如果不接近,请检查是否是日期区域性问题。假设:第一个日期是EU区域性!!!这让我更接近逻辑c我可以使用。因为这些都是特定用户的登录,所以我必须考虑年假或b之类的事情
    # 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.
    
    }