views:

1079

answers:

6

I got a last time (and urgent) requeriment of an "event" that needs to be scheduled the same day of every month.

Say of you set the start date on the 1st May you should get the next events on the 1st of Jun, 1 Jul etc. The problem comes with a start date on the 31st (the next ones could be 30 or 28 depending on the month)

Considering that there are months with different numbers of days (28,30,31) depending on the month itself and the year... what would ba an easy way to setup this?

Consider the following (and flawed) nextmonth function:

$events = array()

function nextmonth($date) {
   return $date+(60*60*24*30);
}
$curr = $start;
while($curr < $end) {
    $events[ = $curr;
    $curr = nextmonth($curr);
}

Edited to add: The problem for me is, simply enought, is to solve what the number of days of any given month is and thus get the next corresponding date..

A: 

Since months are so varied in size, wouldn't the best way to set the next month be something like: this day, next month except if this day doesn't exist next month.

Example:

June 5, 2009, next month would be July 5, 2009
August 31, 2009, next month would be September 30, 2009

or simply, strtotime("+1 month")

St. John Johnson
yes, there it goes.. but the problem for me, simply enought, is to solve what the number of days of any given month is..
Guillermo
@ Guillermo, you don't need to worry about that. The strtotime("+1 month"), literally that, takes care of it.
James Skidmore
this is what I though but:echo date("Y-m-d", strtotime("2009-01-30 +1 month"));resolves as 2009.03.02
Guillermo
It's +1 month, for the current the amount of days in the month your +1'ing!
Mark Tomlin
+3  A: 

I recommend reading the following comment on php.net. strtotime() (php.net)

Edit: The next answer gives the "summary" of the link I posted for those not able to decipher the content shown there.

Michael
Looks interesting.. if you would post this here, someone else will get the chance to get his answer here by looking here..
Guillermo
+6  A: 

Update:

This will give you the number of days in given month:

echo date('t', $timestamp);

See: date()

Old answer:

I'm not sure about the algorithm you're thinking of but I believe this will help you:

echo date('d-M-y', strtotime('next month'));
Ionuț G. Stan
+1 That's what I would do in this situation.
karim79
strtotime("2009-01-30 +1 month"); resolves as 2009.03.02 not usefull in my case
Guillermo
@Guillermo, if you want to map January 31st to February 28th, then what day corresponds to January 28th? Still February 28th?
Ionuț G. Stan
+2  A: 

This will return proper timestamp for $X months ahead: mktime(0,0,0,date("m")+$X,date('d'),date("Y"));

Thinker
+1 This seems more natural-- break up the date and add stuff to the components to get what you want.
Kekoa
+1, I tested this and it works fine when the current month plus x equals a number greater than 12. It increments the year correctly. Also if the day number doesn't exist in the month it will move to the next month with the extra days.
gradbot
just tested your test case "2009-01-30" +1 month and this also returns 2009-3-2
gradbot
A: 

How about this function:

    function getNextMonthN($date, $n = 1) {
      $newDate = strtotime('+' . $n . ' months', $date);
      if (date('j', $date) !== (date('j', $newDate))) {
     $newDate = mktime(0, 0, 0, date('n', $newDate), 0, date('Y', $newDate));
      }
      return $newDate; 
    }

There is another solution on the php.net manual site under the strtotime entry in the comments.

Brian Fisher
+1  A: 

Tried this as a lark, and it actually works

strtotime('last day next month')

So :

$today_next_month = strtotime('this day next month');
$last_day_next_month = strtotime('last day next month');
if (date('d', $today_next_month) < date('d', $last_day_next_month)){
    $date = date('m-d-Y', $last_day_next_month); 
} else {
    $date = date('m-d-Y', $today_next_month);
}
echo "And the winner is : $date<br/>";
Sam Heller
<?php echo date('r', strtotime('last day next month', gmmktime(0, 0, 0, 1, 30, 2009))); ?>I have to say, I did not expect this to work at all. But, it did!
Mark Tomlin