DateTime subtraction not working in PowerShell - assignment vs. equality operator
Today (2017-05-29) I am using PowerShell 5.0.10586.117 on Windows 7 Enterprise and run the following (shortened):
$dateOfLicense = "2017-04-20"
$dateOfToday = '{0:yyyy-MM-dd}' -f (Get-Date)
$TimeDifference = [DateTime]$dateOfToday - [DateTime]$dateOfLicense
if (($TimeDifference) = 14)
{
Write-Host "test"
}
Even the difference between both days is 39, my code jumps in the if-clause and sends "test" to screen.
What am I doing wrong here?
You are assigning 14
to $TimeDifference
. Instead you wan't to compare the Days
property using -le
:
if ($TimeDifference.Days -le 14)
{
Write-Host "test"
}
To complement Martin Brandl's helpful answer:
Like many other languages - but unlike VBScript, for instance - PowerShell uses distinct symbols for:
- the assignment operator (
=
) - vs. the equality test operator (
-eq
).
This distinction enables using assignments as expressions, which is what you inadvertently did:
if ($TimeDifference = 14) ... # same as: if (($TimeDifference) = 14) ...
assigns 14
to variable $TimeDifference
, as Martin explains, and, because the assignment is (of necessity, to serve as a conditional for if
) enclosed in (...)
, returns the assigned value (the inner (...)
around $TimeDifference
make no difference here, however) and that value is used as the Boolean conditional for if
.
That is, the (...)
expression evaluated by if
has value 14
- a nonzero number - and is therefore interpreted as $true
in this Boolean context, irrespective of the original value of $TimeDifference
.
Note:
-
To learn more about PowerShell's operators, run
Get-Help about_Operators
-
To learn about how PowerShell interprets arbitrary values as Booleans in conditionals (to-Boolean coercion), see the bottom section of this answer.
-
To test variables or expressions that already are Booleans, just use them as-is or, if necessary, negate them with
-not
(!
); e.g.:if ($someBoolean) { # Better than: if ($someBoolean -eq $true) if (-not $someBoolean) { # Better than: if ($someBoolean -eq $false)
Finally, here's a streamlined version of your code that doesn't require intermediate variables, uses a cast to convert the string to a [datetime]
instance and uses [datetime]::now
, the more efficient equivalent of Get-Date
(though that will rarely matter).
if (([datetime]::now - [datetime] '2017-04-20').Days -eq 14) {
"test"
}
Note how "test"
as a statement by itself implicitly sends output to PowerShell's (success) output stream, which prints to the console by default.Write-Host
bypasses this stream and should generally be avoided.