I failed to find a proper solution to this issue. As you see in Example #3 in the PHP documentation, they state that one must beware when adding months using the DateInterva
If your goal is to strictly increment by user-friendly months (thus, 3 months from January 21st should be April 21st), with the exception that shorter membership months get shortened (thus, 1 month from January 31st is February 28th/29th), then you only need to go back a few days if you crossed over into the next month:
function addMonths($date,$months) {
$orig_day = $date->format("d");
$date->modify("+".$months." months");
while ($date->format("d")<$orig_day && $date->format("d")<5)
$date->modify("-1 day");
}
$d = new DateTime("2000-01-31");
addMonths($d,1);
echo $d->format("Y-m-d"); // 2000-02-29
The issue is that each month can have a different number of days in them. The question is what you're doing when you want to increment a date by 1 month. Per the PHP documentation if you're on January 31st (or 30th) and you add 1 month, what is the expected behavior?
February only has 29 days in it. Do you want to be set to the last day of the month? You're generally safer incrementing by a set number of days if that's what you're looking for, or a static date based on the current date. Without knowing what you're trying to accomplish when you increment your month, it's tough to say how to watch for an error.
EDIT:
As someone mentions in the similar post commented by Mike B above, you probably want to do something where you (in pseudocode):
1) Use cal_days_in_month() for the next month and save that number to a variable x
2) If x >= current billing DOB, increment and be done
3) DateTime::modify('last day') (havent used this before but something along these lines) to set the date to the last date of the next month (set it to the 1st of the next month, then last day?)
Worth noting is that if you use the variable here as the new billing value, you'll wipe out your original value. I would save an extra DB value that's "first billing date" or just "billing_day_of_month" or something, and use that to figure out the day of month that you should be looking at