8

I am learning Windows PowerShell, and I am trying to get the months difference given two dates:

For example: end: 2014-06-01
now: 2014-01-10
answer: 6 months

$now = get-date
    $date = $end -as [DateTime];
    if (!$date)
    {
      'You entered an invalid date'
    }
    else
    {
      $nts = ($now - $end).Months
      write-output $nts
    }

I have tried everything, and I can't get the correct months in PowerShell. How can I fix it?

6 Answers 6

23

Where is the $endFromDatabase variable coming from? That part isn't clear in your post.

To demonstrate subtracting DateTime objects, see the example below.

$TimeSpan = [DateTime]'2014-01-10' - [DateTime]'2014-01-06';

You will receive a System.TimeSpan as a result from the operation, so you can explore members such as:

$TimeSpan.TotalDays;

My guess is that you just need to fix the value in the $endFromDatabase variable, so that it can be cast into a System.DateTime object.

Background

Subtracting a [DateTime] object from another [DateTime] object works, because the [DateTime] class overloads the subtraction operator, which results in the op_subtraction Intermediate Language (IL) method. You can examine this in a .NET object explorer tool, such as .NET Reflector.

You'll notice that there is a second overload of the subtraction operator, which allows you to subtract a [TimeSpan] object from a [DateTime] object.

.NET Reflector Screenshot

Sign up to request clarification or add additional context in comments.

1 Comment

Returning just a [timespan] doesn't really answer the question, because it doesn't translate to a month difference without a calendar date reference. On April 1, -30 days is 2 months ago. On May 1 it's last month.
13

Something like this?

$begin = [datetime]'02/10/2011'
$end   = [datetime]'01/10/2013'

$monthdiff = $end.month - $begin.month + (($end.Year - $begin.year) * 12)
$monthdiff

23

Comments

1

A few of the answers above don't take into consideration counting whole months, e.g. if you're counting from the 17th, you don't count a new whole month till you reach the 17th of following months.

Best way I found to do this I added in another Stackflow question:

https://stackoverflow.com/a/68894016/11951959

Comments

0

This is as close as I can get to your original code. Subtracting datetime's results in a timespan, which has a days member, but not a months member. ($date - $now).gettype()

$end = '2014-06-01'
$now = get-date
$date = $end -as [DateTime];
if (!$date) 
{
  'You entered an invalid date'
}
else 
{
  $nts = ($date - $now).days/30
  write-output $nts
}

Comments

0

You could also use New-Timespan for this

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-timespan?view=powershell-7.1

The New-TimeSpan cmdlet creates a TimeSpan object that represents a time interval. You can use a TimeSpan object to add or subtract time from DateTime objects.

Time difference between a file's lastwritetime and now:

enter image description here

New-TimeSpan -Start (get-childitem  test.txt).LastWriteTime -end (get-date)

enter image description here

Comments

0

In case you need full/whole elapsed months [and days], following does seem to do the trick. My attempts at deterministic approach just ended up as an attempt to reinvent AddMonth logic, so might as well use the source.

Months only:

$months = 0
while($startDate.AddMonths($months) -le $endDate)
{
    $months = $months + 1
}
$months = $months - 1

A bit more efficient, a little less readable:

$years = 0
if(($endDate.Year - $startDate.Year) -gt 0)
{
    $years = $endDate.Year - $startDate.Year - 1
}
$months = 12 * $years

while($startDate.AddMonths($months) -le $endDate)
{
    $months = $months + 1
}
$months = $months - 1

If you need months and days:

$months = 0
while($startDate.AddMonths($months) -le $endDate)
{
    $months = $months + 1
}
$months = $months - 1

$days = 0
while($startDate.AddMonths($months).AddDays($days) -le $endDate)
{
    $days = $days + 1
}
$days = $days - 1

Write-Host "$months month(s) and $days day(s)"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.