megapro17
megapro17

Reputation: 425

Powershell equals dates is not equals

I'am trying to compare two dates, if they not equals, I write current date to txt file, but I always getting two dates different, even if I wrote new date to file right now.

$lastBackup=Get-Date (Get-Content -Path last_backup.txt)
"First date is: $lastBackup"
write-host

$lastModified = Get-Date ((Get-Item "My folder").LastWriteTime)
"Second date is: $lastModified"
write-host

if ($lastBackup -ne $lastModified)
{
    Set-Content -Path .\last_backup.txt -Value $lastModified -NoNewline
    "Dates are not equal"
    write-host
}

Output:

First date is: 03/13/2019 23:35:17

Second date is: 03/13/2019 23:35:17

Dates are not equal

$lastBackup and $lastModified are both DateTime objects. What's wrong with this script?

Upvotes: 1

Views: 1285

Answers (2)

mklement0
mklement0

Reputation: 437090

  • You cannot generally infer from the string representation of [datetime] (System.DateTime) instances whether they're exactly equal.

    • The exact point in time stored in a [datetime] instance is generally not fully reflected in string representations.
  • Two [datetime] instances are only considered equal if their .Ticks property values are equal.

    • The .Ticks property contains a [long] (System.Int64) value that expresses a point in time in terms of 100-nanosecond intervals since midnight of January 1st of the year 1 A.D. in the Gregorian Calendar.

Therefore, if you want to compare [datetime] instances (just called dates in the discussion below) at a higher level of granularity, additional work is needed:

Use the appropriate Get-Date parameters to set all lower levels of granularity to 0:

For instance, to compare dates at the granularity of seconds (to see if they fall into the same calendar second), set the -MilliSecond component to 0:

$dtNow = Get-Date
$dtNowAgain = Get-Date

# This - predictably - returns $false, because the dates aren't exactly equal,
# given that the date values will at least differ by milliseconds, and
# possibly also by the seconds value.
$dtNow -eq $dtNowAgain

# You can abstract away the difference by setting the milliseconds
# component to 0 - this will *typically* return $true
# NOTE: If a new calendar second happened to start between setting $dtNow
#       and $dtNowAgain, this will return $false.
(Get-Date $dtNow -MilliSecond 0) -eq (Get-Date $dtNowAgain -MilliSecond 0)

To compare at the level of minutes (to see if they both fall into the same calendar minute), you must set both -Second and -MilliSecond to 0:

# This will *typically* return $true.
# NOTE: If a new calendar minute happened to start between setting $dtNow
#       and $dtNowAgain, this will return $false.
(Get-Date $dtNow -Second 0 -MilliSecond 0) -eq (Get-Date $dtNowAgain -Second 0 -MilliSecond 0)

Note: The advantage of the above approach over string-based comparison is that it ultimately still performs numerical comparisons, so that not only equality testing works (-eq), but also inequality testing (-lt / -le / -gt / -ge), as well as sorting.

Upvotes: 2

Max
Max

Reputation: 771

Round dates to seconds/minutes/5th minutes, etc before comparsion. You can do either:

$date = Get-Date
$date.ToString("yyyy-MM-dd HH:mm:ss.fff")
$roundedDate = Get-Date -Year $date.Year -Month $date.Month -Day $date.Day -Hour $date.Hour -Minute $date.Minute -Second $date.Second -Millisecond 0
$roundedDate.ToString("yyyy-MM-dd HH:mm:ss.fff")

or see this link https://jrich523.wordpress.com/2011/10/03/rounding-a-date-in-powershell/

Upvotes: 0

Related Questions