MadScientist
MadScientist

Reputation: 565

Strange occurance when looping through dates PHP

So I loop through using for to list out months from current going back 11 months using this

$dateFormat = 'Y-m';
$currentMonth = date($dateFormat);
$monthsToGoBack = 11;   
$months = array($currentMonth);

for($m = 1;$m<=$monthsToGoBack;$m++){
    $months[] = date($dateFormat, strtotime("-".$m." Months"));
    echo $m.'<br>';
}

The strangest thing is happening when I run the script This is how the array is build there is no February but double for March. Does any one have any idea what is causing this.

    Array
(
    [0] => 2014-10
    [1] => 2014-09
    [2] => 2014-08
    [3] => 2014-07
    [4] => 2014-06
    [5] => 2014-05
    [6] => 2014-04
    [7] => 2014-03
    [8] => 2014-03
    [9] => 2014-01
    [10] => 2013-12
    [11] => 2013-11
)

ANSWER TO PROBLEM

for($m = 1;$m<=$monthsToGoBack;$m++){
    $months[] = date($dateFormat,strtotime(date('Y-m') . '-01 -'.$m.' months'));
}

Upvotes: 0

Views: 39

Answers (2)

KIKO Software
KIKO Software

Reputation: 16688

This is because you substract the number of seconds in a month. This is unrealiable because there's no fixed amount of seconds in each month.

You need to rewrite your code. Here is a tested example:

$currentYear    = date('Y');
$currentMonth   = date('m');
$monthsToGoBack = 11;

for($monthNo = 0;$monthNo <= $monthsToGoBack;$monthNo++)
{
  $months[] = $currentYear.'-'.str_pad($currentMonth,2,'0',STR_PAD_LEFT);
  $currentMonth--;
  if ($currentMonth == 0)
  {
    $currentYear--;
    $currentMonth = 12;
  }
}

echo '<pre>'.print_r($months,TRUE).'</pre>';

The output is:

Array
(
    [0] => 2014-10
    [1] => 2014-09
    [2] => 2014-08
    [3] => 2014-07
    [4] => 2014-06
    [5] => 2014-05
    [6] => 2014-04
    [7] => 2014-03
    [8] => 2014-02
    [9] => 2014-01
    [10] => 2013-12
    [11] => 2013-11
)

Upvotes: 1

shevron
shevron

Reputation: 3663

I'm guessing this has something to do with today being the 29th and February of this year only having 28 days. Looks like you're trying to iterate over months - I would strongly suggest trying more robust APIs and not relying on strtotime for that. Take a look at the DateTime class and its DateInterval counterpart which allows you to do calendar arithmetic operations very easily and probably in a safer way.

For example, something like (I did not test this):

$d = new DateTime();
$days = $d->format('d') - 1; // days to 1st of the month
$d->sub(new DateInterval("P{$days}D"));

$dateFormat = 'Y-m';
$monthsToGoBack = 11;
$months = array($d->format($dateFormat));

for($m = 1; $m <= $monthsToGoBack; $m++){
    $d->sub(new DateInterval("P1M"));
    $months[] = $d->format($dateFormat);
    echo $m . '<br/>';
}

Upvotes: 0

Related Questions