PHP Number of months between 2 dates

Hi Guys,
I know this is probably very simple, but I can't seem to find a solution that's right for me.

I'm getting one date from the db as "2011-11-21" and placing that value in the variable "$LastPaymentDueDate"

I'm also creating a future date such as "2012-04-01" and placing that value in the variable "$NextPaymentDueDate"

I don't care about partial months because everyone is supposed to pay up on the first day of every month. I just want a count to tell me how many months a particular payment is overdue by.

Can you help?
Thanks,
Sas
LVL 1
sasnaktivAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DavidPresidentCommented:
I'll assume you will have no problem parsing into variables

LAPSEDMONTHS = (FUTUREYEAR - LASTPAYMENTYEAR) * 12 + FUTUREMONTH - LASTPAYMENTMONTH.

Just convert everything into months.   (If number is <= 0, then they are current)
0
sasnaktivAuthor Commented:
Thanks.
How do I determine from my variables "FUTUREYEAR" and "LASTPAYMENTYEAR"?

And shall I assume "FUTUREMONTH" and "LASTPAYMENTMONTH" would follow the same logic?
0
Ray PaseurCommented:
Have a look at this article.  The term month is ambiguous because months are not consistent in the elapsed time,  like days or weeks.  While you read that I will try to find a solution that works consistently.
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_201-Handling-date-and-time-in-PHP-and-MySQL.html
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

Ray PaseurCommented:
Sorry, Sas - small family emergency.  I cannot work this out now.  Look into mktime() and you will find the best answer.  If you're still unsure tomorrow, please post whatever you have tried and I will get back to you.   Best regards, ~Ray
0
sasnaktivAuthor Commented:
Thanks Ray,
I hope your family emergency isn't anything serious.

I checked out your link. It's quite impressive. I notice that it is gathering dates a different way than I am. I already have both dates formatted as YYYY-mm-dd. So I don't know how to apply your demos.

Take care,
Sas
0
designatedinitializerCommented:
Check this out:

<?php
// it was a warm winter day...
$dateB = new DateTime('2012-01-31'); 
print $dateB->format('Y-m-d')."<br/>";
// 3 months later... it's not 31!
$dateB->add(date_interval_create_from_date_string('3 months'));
print $dateB->format('Y-m-d')."<br/>";
?>

Open in new window


You have a whole bunch of methods in the DateTime object.
Just skim thru the corresponding PHP manual pages and you'll get to what you want pretty fast.
0
Ray PaseurCommented:
Sorry to have taken so long to get back to you.  I wrote a demonstration code example, but lost track of the question on EE so I couldn't figure out where to put it!
See http://www.laprbass.com/RAY_temp_sasnaktiv.php
Outputs:
FROM January 2012 TO March 2012 THERE ARE 2 MONTHS
FROM December 2011 TO March 2012 THERE ARE 3 MONTHS
FROM December 2011 TO TODAY THERE ARE 3 MONTHS
FROM -30 DAYS TO TOMORROW THERE ARE 1 MONTHS
FROM -3 DAYS TO TODAY THERE ARE 0 MONTHS
FROM LAST MONTH TO TODAY THERE ARE 0 MONTHS
FROM 2012-03-5 TO TODAY THERE ARE 0 MONTHS
<?php // RAY_temp_sasnaktiv.php
error_reporting(E_ALL);
echo "<pre>";


// HOW MANY MONTHS BETWEEN TWO DATES?


date_default_timezone_set('America/Chicago');

function howManyMonths($alpha, $omega)
{
    // NORMALIZE THE OLD MONTH
    $a = strtotime($alpha);
    if (!$a) return "ERROR $alpha";
    $a = date('Y-m-1', $a);

    // NORMALIZE THE NEW MONTH
    $z = strtotime($omega);
    if (!$z) return "ERROR $omega";
    $z = date('Y-m-1', $z);

    $n = 0;
    while ($a < $z)
    {
        $a = date('Y-m-1', strtotime($a . ' + 1 MONTH'));
        $n++;
    }

    // ACTIVATE THIS LINE FOR TESTING
    echo PHP_EOL . "FROM $alpha TO $omega THERE ARE $n MONTHS";
    return $n;
}

// TEST CASES
howmanymonths('January 2012', 'March 2012');
howmanymonths('December 2011', 'March 2012');
howmanymonths('December 2011', 'TODAY');
howmanymonths('-30 DAYS', 'TOMORROW');
howmanymonths('-3 DAYS', 'TODAY');
howmanymonths('LAST MONTH', 'TODAY');

// ANY DAY IN THIS MONTH
$x = rand(1,28);
howmanymonths( date("Y-m-$x"), 'TODAY');

Open in new window

0
sasnaktivAuthor Commented:
Thanks for the attention designatedinitializer
I ran your code exactly as you posted it and I get the following error.
What can be done to resolve this error?
Thanks.
SAS

2012-01-31
Fatal error: Call to undefined method DateTime::add() in /home/content/p/h/a/pharmacallmobi/html/NEXTSEATING.COM/CONTENT/Nxt_manager/admin/RAY.php on line 8

<?php 
error_reporting(E_ALL);

// it was a warm winter day...
$dateB = new DateTime('2012-01-31'); 
print $dateB->format('Y-m-d')."<br/>";
// 3 months later... it's not 31!
$dateB->add(date_interval_create_from_date_string('3 months'));
print $dateB->format('Y-m-d')."<br/>";
?>

Open in new window

0
sasnaktivAuthor Commented:
Hi Ray,
Thanks for the help. I hope your family emergency was not serious.
Of course I made some changes to your code in order to get it to work with my db. I'm getting some odd results though, and I hope you can straighten me out.

Below is what is being returned:
FROM 2012-03-09 TO 2012-03-31 THERE ARE 0 MONTHS -- THIS IS OBVIOUSLY CORRECT
FROM 2012-03-09 TO 2012-05-01 THERE ARE 1 MONTHS  -- THE MONTH COUNT SEEMS CORRECT BUT THIS SHOULD BE 2012-04-01   IT ACTUALLY RETURNS 2012-05-01. WHY???
FROM December 2011 TO March 2012 THERE ARE 0 MONTHS
FROM 2012-03-19 TO TODAY THERE ARE 0 MONTHS

<?
include "MySQL_RAY_temp_sasnaktiv.inc";

$link = mysql_connect ($dbhost, $dbusername, $dbuserpass);
if (!mysql_select_db($dbname)) die(mysql_error());

     $getlist="SELECT * FROM `Members`"; //select e-mails in ABC order

      $getlist2=mysql_query($getlist) or die("Could not get your members list");

$LastPaymentDate= "$getlist3[payment_made]";
$PaymentDueDate = date("Y-m-d");

$NextMonth = mktime(0, 0, 0, date("m")+1, date("d"), date("y"));
$NxtBillDate = date("Y-m-01", $NextMonth); // THIS SHOULD BE 2012-04-01  BUT IT RETURNS 2012-05-01. WHY???

echo "<pre>";

date_default_timezone_set('America/New_York');

function howManyMonths($alpha, $omega)
{
    // NORMALIZE THE OLD MONTH
    $a = strtotime($alpha);
    $a = date("Y-m-d");
    if (!$a) return "ERROR $alpha";

    // NORMALIZE THE NEW MONTH
    $z = strtotime($omega);
    if (!$z) return "ERROR $omega";
    $z = date('Y-m-1', $z);

    $n = 0;
    while ($a < $z)
    {
        $a = date('Y-m-1', strtotime($a . ' + 1 MONTH'));
        $n++;
    }
    // ACTIVATE THIS LINE FOR TESTING
    echo PHP_EOL . "FROM $alpha TO $omega THERE ARE $n MONTHS";
    return $n;
}
// TEST CASES
howmanymonths("$LastPaymentDate", "$PaymentDueDate");
howmanymonths("$LastPaymentDate", "$NxtBillDate");
howmanymonths('December 2011', 'March 2012');

// ANY DAY IN THIS MONTH
$x = rand(1,28);
howmanymonths( date("Y-m-$x"), 'TODAY');
?>

Open in new window

0
designatedinitializerCommented:
I ran your code exactly as you posted it and I get the following error.
What can be done to resolve this error?
It means your PHP installation doesn't support the DateTime class.
You can do it simply like this:
<?php
// Find how many months have passed between date1 and date2
$date1 = "2011-11-21";
$date2 = "2012-04-01";

$one = explode('-',$date1);
$two = explode('-',$date2);

$aMonths = (int)$one[0]*12+(int)$one[1];
$bMonths = (int)$two[0]*12+(int)$two[1];
$months  = $bMonths-$aMonths;

print "From $date1 to $date2 there are $months whole months.";
?>

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
designatedinitializerCommented:
You can also do it straigh in your SQL SELECT query, but for that I need to know how you're storing that data. You can however check the MySQL manual, the date and time functions section.
0
sasnaktivAuthor Commented:
Thanks designatedinitializer

I think that's working, but tell me why am I getting April (05) instead of May (04)
with the following code:
$NextMonth = mktime(0, 0, 0, date("m")+1, date("d"), date("y"));
$NxtBillDate = date("Y-m-01", $NextMonth); // THIS SHOULD BE 2012-04-01  BUT IT RETURNS 2012-05-01. WHY???

Open in new window

0
designatedinitializerCommented:
because you have
date("m")+1

?
0
sasnaktivAuthor Commented:
What should it be?
date("m")   returns this month 03
date("m")+0 returns this month 03
date("m")+1 returns 2 months ahead to 05
date("m")+2 also returns 2 months ahead to 05
date("m")+3 returns 4 months ahead to 07

What happened to 04 & 06?
Why is this so screwy?
0
Ray PaseurCommented:
FROM 2012-03-09 TO 2012-05-01 THERE ARE 1 MONTHS  -- THE MONTH COUNT SEEMS CORRECT BUT THIS SHOULD BE 2012-04-01   IT ACTUALLY RETURNS 2012-05-01. WHY???
This only happens today, March 31, because April 31 does not exist.  So the Unix timestamp generated by mktime() flops over to the next month.  The meaning of the term "month" is ambiguous.  Unlike weeks that have seven days every week, the number of days in a month can change.  I think you'll be OK if you use the function I posted earlier.  Best of luck with your project, ~Ray
0
Ray PaseurCommented:
Afterthought... You might also try this for mktime()

$NextMonth = mktime(0, 0, 0, date("m")+1, '1', date("y"));
0
sasnaktivAuthor Commented:
Thanks Ray,
Will that function properly during months that have only 30 days or 28 days?
Sas
0
Ray PaseurCommented:
Yes, I think so.  It only looks at the first day of the month - not the number of days in the month.
0
sasnaktivAuthor Commented:
Thanks guys,
Both solutions seem to work for me. I just wish I could add more points.
Sas
0
DavidPresidentCommented:
For what it is worth, the ultimate answer is still the equation I posted in 37759579, just different variable names.   ;)

LAPSEDMONTHS = (FUTUREYEAR - LASTPAYMENTYEAR) * 12 + FUTUREMONTH - LASTPAYMENTMONTH.
0
sasnaktivAuthor Commented:
That may be the case, but you never got back to me about my follow up question:

"How do I determine from my variables "FUTUREYEAR" and "LASTPAYMENTYEAR"?
And shall I assume "FUTUREMONTH" and "LASTPAYMENTMONTH" would follow the same logic?"

If you had I might have had the solution much earlier than I did.
Just please be aware that I do indeed appreciate your help.
Thanks,
Sas
0
DavidPresidentCommented:
Agreed, I had the premise that you knew how to assign variable names and put the values in them, but the engineering problem was a single line of code that dropped the days of the month and took (YYYY * 12 + M) and subtracted the difference.  I'm not complaining, not asking or implying points, just pointing out that this was a one-line of code simple solution ;)
0
designatedinitializerCommented:
dlethe:
you were also assuming that the data was separated in years, and months, and that both were integers you could simply add up and multiply.
The question showed dates in the form of strings...
0
sasnaktivAuthor Commented:
I appreciate simplicity. I hope we can work together on my next problem child.
Thanks for your help,
Sas
0
DavidPresidentCommented:
same here, glad it worked out for you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.