日期时间比较,让线程在不应该进行的时间进行

时间:2019-01-16 21:21:37

标签: powershell datetime comparison

我有一个备份脚本,该脚本每天晚上都将文件放入带日期的目录中。我在下面还有另一个脚本,该脚本遍历了带日期的目录,如果它在我要删除的范围内,我将删除该目录,并保留周六的日期文件。由于某些原因,对于日期为2019年1月12日星期六的目录,即使if语句应指示不会删除它,该目录也会被删除。

这是我的代码:

function WeeklyCleanup($folderWeeklyCleanupDatedSubdirs) {
   #find out date range to cleanup
   $lastSaturday = GetLastSaturdayDate
   $lastSaturday = [datetime]$lastSaturday
   $weekAgoSunday = GetWeekAgoSundayDate
   $weekAgoSunday = [datetime]$weekAgoSunday
   #find out filename with Saturday date before current date but within week
   Get-ChildItem $folderWeeklyCleanupDatedSubdirs | ForEach-Object {
      write-output $_
      #check to see if item is before day we want to remove
      $temp = $_
      $regex = [regex]::Matches($temp,'([0-9]+)-([0-9]+)-([0-9]+)')
      if($regex.length -gt 0) #it matched
      {
         $year  = $regex[0].Groups[1].Value
         $month = $regex[0].Groups[2].Value
         $day   = $regex[0].Groups[3].Value
         write-output $year
         write-output $month
         write-output $day
         write-output "*************"
         $dirDate = $regex[0].Groups[0].Value + " 12:00:00 PM"
         write-output $dirDate

         if($dirDate.length -gt 0) #it matched
         {
            $dateTimeObjectFromRegex = [datetime]$dirDate
##########此下一条语句让$ dateTimeObjectFromRegex of 1/12/2019通过不该通过的时间。请参阅下面的时间比较
            if(([datetime]$dateTimeObjectFromRegex -lt [datetime]$lastSaturday) -and ([datetime]$dateTimeObjectFromRegex -ge [datetime]$weekAgoSunday)) #we're removing extra ones over last week, keep Saturday
            {
               $dirPathToRemove = Join-Path -path $folderWeeklyCleanupDatedSubdirs -ChildPath $temp.ToString()
               Get-ChildItem -Path $dirPathToRemove #list the dir
               #remove dir
               if(-Not (Test-Path $dirPathToRemove )) #-PathType Container
               {
                  $global:ErrorStrings.Add("Exception: No such path, $dirPathToRemove;;  ")
                  write-output  "++ Error: An error occured during copy operation. No such path, $dirPathToList ++"
               }
               else
               {
                  #remove dir and subdirs
                  Remove-Item $dirPathToRemove -Force -Recurse
                  Get-ChildItem -Path $dirPathToRemove #list the dir
               }
               #Write-Output $_
               #Write-Output " 1 "
            } #if within last week
         } #if dirDate length
      } #if regex matched

   } #get-childItem
}

function GetLastSaturdayDate()
{
   $date = Get-Date #"$((Get-Date).ToString('yyyy-MM-dd'))"
   #for($i=1; $i -le 7; $i++){
   #   if($date.AddDays(-$i).DayOfWeek -eq 'Saturday') #if found Saturday
   #   {
   #      $date.AddDays(-$i)
   #      $newDate = $date.AddDays(-$i)
   #      break
   #   }
   #}
   $newdate = $date.AddDays(-($date.DayOfWeek+1)%7)
   return $newdate
}

function GetWeekAgoSundayDate()
{
   $numberOfWeeks = 1; #week ago
   $date = Get-Date #"$((Get-Date).ToString('yyyy-MM-dd'))"
   #for($i=1; $i -le 7; $i++){
   #   if(($date.AddDays(-$i).DayOfWeek -eq 'Sunday') -and ($date.AddDays(-$i) -ne  $date)) #if found a Sunday and it's not today
   #   {
   #      $date.AddDays(-$i)
    #     $newDate = $date.AddDays(-$i)
    #     break
    #  }
   #}
   #$newdate = $date.AddDays(-($date.DayOfWeek+1)%0)
   $numDaysSincePreviousDate = $date.DayOfWeek.value__ + 0 #0 is Sunday
   ([System.DateTime] $previousDayOfWeek = $date.AddDays(- $numDaysSincePreviousDate)) | Out-Null
   $previousDate = $previousDayOfWeek.AddDays(-($numberOfWeeks *7)).ToString("MM-dd-yyyy")
   return $previousDate
}

使用以下参数调用WeeklyCleanup脚本:

$folderToCleanupDatedSubdirs = [System.IO.DirectoryInfo]"E:\Bak_TestDatedFolderCleanup"

用于时间比较:

Directory项目到LocRobo_2019-01-12-一旦获得带有时间戳的正则表达式,就为$ dirDate变量添加了12:00:00 PM的时间。这将变成$ dateTimeObjectFromRegex。调试器将其显示为2019年1月12日(星期六)下午12:00:00

运行程序时,我将在2019年1月12日星期六下午3:59:04收到$ lastSaturday

当我运行程序时,调试器还将$ weekAgoSunday显示为2019年1月6日星期日12:00:00 AM

从我所看到的,应该不应该通过if语句删除2019年1月12日的目录。

我尝试将日期强制转换为日期时间,以确保即使在上面强制转换,也不会在if语句中进行字符串比较。

我一直在寻找这些链接,以获取有关此的更多信息,但对我来说似乎是正确的:

dateTimeComparisons not working expectedly

convert string to datetime

我能想到的是,它仍将if语句比较的第一部分中的日期时间像字符串一样对待,因此它认为3:59 PM大于12:00 PM。任何想法如何使此日期检查工作?我不在乎时间,只是想确保它不会清除过去一周的星期六日期文件,而是仅清除该周的其他目录。

更新 进行了以下@brianist建议的更改,效果很好。到目前为止是这样。周六和周日功能未更改。他要我发布。如果他还有其他建议如何使用它来处理/比较上周六和周从周六返回的内容,而没有转换,则AgoSunday看起来不那么笨拙/更容易阅读。谢谢布莱恩!

#do weekly cleanup of DisasterBackup folder
function WeeklyCleanup($folderWeeklyCleanupDatedSubdirs) {
   #find out current date
   $currentDate = "$((Get-Date).ToString('yyyy-MM-dd'))"  #example 2019-01-15
   $currentDayOfWeek = (get-date).DayOfWeek.value__ #returns int value for day of week
   #find out current day of week
   $lastSaturday = GetLastSaturdayDate
   $lastSaturday = [datetime]$lastSaturday #if we take away extra casts it won't do comparison line (-lt and -ge)
   $weekAgoSunday = GetWeekAgoSundayDate
   $weekAgoSunday = [datetime]$weekAgoSunday #if we take away extra casts it won't do comparison line (-lt and -ge), and can't move cast before function call because it isn't recognizing function anymore if I do
   #find out filename with Saturday date before current date but within week
   #get each dir item to check if we need to remove it
   Get-ChildItem $folderWeeklyCleanupDatedSubdirs | ForEach-Object {
      write-output $_
      #check to see if item is before day we want to remove
      $temp = $_
      if($_.Name -match '(\d{4}-\d{2}-\d{2})$'){ #regex
         write-output $Matches[1]
         $dirDate = Get-Date $Matches[1] #turn regex into date
         if(([datetime]$dirDate.Date -lt [datetime]$lastSaturday.Date) -and ([datetime]$dirDate.Date -ge [datetime]$weekAgoSunday.Date)) #we're removing extra ones over last week, keep Saturday
         {
            $dirPathToRemove = Join-Path -path $folderWeeklyCleanupDatedSubdirs -ChildPath $temp.ToString()
            Get-ChildItem -Path $dirPathToRemove #list the dir
            #remove dir
            if(-Not (Test-Path $dirPathToRemove )) #-PathType Container
            {
               $global:ErrorStrings.Add("Exception: No such path, $dirPathToRemove;;  ")
               write-output  "++ Error: An error occured during copy operation. No such path, $dirPathToList ++"
            }
            else
            {
               #remove dir and subdirs
               Remove-Item $dirPathToRemove -Force -Recurse
               Get-ChildItem -Path $dirPathToRemove #list the dir
            }

         } #if within last week
      } #if regex matched

   } #get-childItem
}

1 个答案:

答案 0 :(得分:1)

重新阅读您的最后一句话,我现在看到您的意图是忽略时间,而不是将它们包括在比较中。

比较时,您想使用[DateTime]对象是正确的,但请注意,这些对象始终包含一个时间。

您可以方便地使用此类对象的.Date属性,该属性返回一个新的对象,时间设置为午夜。这对于进行比较很有用,因为时间不再是一个因素。

从下面拉出我修改过的if语句,您可以这样做:

if ($dirDate.Date -lt $lastSaturday.Date -and $dirDate.Date -ge $weekAgoSunday.Date) {
    # do stuff
}

现在您只比较日期,而忽略时间!


根据您所显示的内容,if语句似乎可以正常工作。总而言之,您说:

$dateTimeObjectFromRegexSaturday, January 12, 2019 12:00:00 PM

$lastSaturdaySaturday, January 12, 2019 3:59:04 PM

$weekAgoSundaySunday, January 6, 2019 12:00:00 AM

条件是:

if(([datetime]$dateTimeObjectFromRegex -lt [datetime]$lastSaturday) 
-and ([datetime]$dateTimeObjectFromRegex -ge [datetime]$weekAgoSunday))

因此,用伪代码是:

if (
    ("January 12, 2019 12:00:00 PM" is earlier than "January 12, 2019 3:59:04 PM") # true
    and
    ("January 12, 2019 12:00:00 PM" is later or the same as "January 6, 2019 12:00:00 AM") # true
) # true

我确实要指出,您正在做很多不必要的日期时间裁剪和转换,清理这些内容将有助于提高可读性并调试这些类型的问题。

$lastSaturday = GetLastSaturdayDate
$lastSaturday = [datetime]$lastSaturday
$weekAgoSunday = GetWeekAgoSundayDate
$weekAgoSunday = [datetime]$weekAgoSunday

您的函数已经返回了[DateTime]个对象,因此不需要这些强制类型转换。


      $temp = $_
      $regex = [regex]::Matches($temp,'([0-9]+)-([0-9]+)-([0-9]+)')
      if($regex.length -gt 0) #it matched
      {
         $year  = $regex[0].Groups[1].Value
         $month = $regex[0].Groups[2].Value
         $day   = $regex[0].Groups[3].Value
         write-output $year
         write-output $month
         write-output $day
         write-output "*************"
         $dirDate = $regex[0].Groups[0].Value + " 12:00:00 PM"
         write-output $dirDate

这非常复杂,您可以将其简化为以下形式:

if ($_.Name -match '(\d{4}-\d{2}-\d{2})$') {
    # in here, you know the match was successful
    $dirDate = Get-Date $Matches[1] # double check this, might need .Groups or something

    if ($dirDate -lt $lastSaturday -and $dirDate -ge $weekAgoSunday) {
        # do stuff
    }
}

可能还有更多优化等。希望对您有所帮助!