views:

329

answers:

5

On a page I want to dynamically list years and all the months in each year so an archive for each month can be viewed. I want to show the current year first but the current year may not be over yet so I only want to show the months that have passed, and the current month. Then I want all years and all months in the past since this year (i.e. 2008).

The PHP code I have created that does the job is below. Is there a more efficient way of achieving this? I am running PHP 5.2.

$current_year = date('Y');
$months = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

// Loop through all the months and create an array up to and including the current month
foreach ($months as $month)
{
    if ($month <= date('m'))
    {
     switch ($month)
     {
      case 1:
       $years[$current_year][] = 'January';
       break;
      case 2:
       $years[$current_year][] = 'February';
       break;
      case 3:
       $years[$current_year][] = 'March';
       break;
      case 4:
       $years[$current_year][] = 'April';
       break;
      case 5:
       $years[$current_year][] = 'May';
       break;
      case 6:
       $years[$current_year][] = 'June';
       break;
      case 7:
       $years[$current_year][] = 'July';
       break;
      case 8:
       $years[$current_year][] = 'August';
       break;
      case 9:
       $years[$current_year][] = 'September';
       break;
      case 10:
       $years[$current_year][] = 'October';
       break;
      case 11:
       $years[$current_year][] = 'November';
       break;
      case 12:
       $years[$current_year][] = 'December';
       break;
     }
    }
}

// Previous years
$years_to_create = $current_year - 2008;

if (!empty($years_to_create))
{
    for ($i = 1; $i <= $years_to_create; $i++)
    {
     $years[$current_year - $i] = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
    }
}
A: 

PHP has a Date() function and an mktime function, you can use these to compare dates and to create dates out of strings etc. Without providing code, i can give you an instruction to somehow make an iteration:

  -> Get current Year

  -> Loop the current year untill the current month is reached

     -> Print Month
Filip Ekberg
Thanks but I know how to do it. I want to know if my code can be made more efficient or not.
DavidM
+2  A: 

try this it will out put a descending list of months/years for the past 5 years

$years = 5;

for ($i = 0; $i < (12* $years); $i++)
{
    if (date('Y',strtotime("-".$i." month")) > (date('Y') - $years) )
    {
      echo date('F Y',strtotime("-".$i." month")) . '<br />'; 
    }
}

Then if you need it in an array, just add to as you go like so

$years = 5;
$myarray = array();

for ($i = 0; $i < (12* $years); $i++)
{
    if (date('Y',strtotime("-".$i." month")) > (date('Y') - $years) )
    {
         $year_key = date('Y') - date('Y',strtotime("-".$i." month")); 
         $myarray[$year_key][] = date('F',strtotime("-".$i." month"));
    }
}

//Write it out to the screen
foreach ($myarray as $yearkey=>$eachyear)
{
    foreach ($eachyear as $eachmonth)
    { 
        echo (date('Y')-$yearkey) . ' ' . $eachmonth . '<br>';
    }
}
Re0sless
That will output all months for the last 5 years whereas for the current year, I only want to output the months that have passed, including the current month. It's fine for Dec 2008 since all the months have passed but in Feb 2009, I only want to show Jan and Feb, for example.
DavidM
You mean in feb 2009 it will show march..december 2004? as the -1 month is working from todays date, it will never show future dats as strtotime has a negative value in it.
Re0sless
I have added the if, but dont have a php server at home to test it
Re0sless
Thanks but I don't want the past 5 years, I only want from 2008. And basic testing your code shows it is slower than mine: 0.009551 0.010196 0.011607 = avrg 0.0105
DavidM
+1  A: 

Revised

function getMonthsFromYear($start = 2008, $end = null, array $months = null) {
    static $sMonths = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
    $thisYear = intval(date('Y'));
    if (!is_array($months) || (count($months) < 12))
        $months = $sMonths;
    if (!is_int($end))
         $end = $thisYear;
    if ($end > $thisYear)
        return array_fill($start, $end - $start + 1, $months);
    if ($start < $end)
        $monthsInDuration = array_fill($start, $end - $start, $months);
    $monthsInDuration[$end] = array_slice($months, 0, (int) date('m'));
    return $monthsInDuration;
}
print_r(getMonthsFromYear());
print_r(getMonthsFromYear(2006));
print_r(getMonthsFromYear(2008, 2010));
OIS
Thanks but your code is slower. My code execuded in 0.000391 0.000319 and 0.000316 with average 0.000342. Your code executed in 0.000361 0.000326 and 0.000325 with average 0.000349. Minimal differences but your code also looks more complex and therefore less readable.
DavidM
My code is more flexible. I also find it easier to read then 2 pages of excess code.
OIS
The code I need doesn't need to be flexible. You find yours easier to read because you wrote it.
DavidM
+2  A: 
$current_year = date('Y');
$months = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
$month_names = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

// Loop through all the months and create an array up to and including the current month

for ($month=1;$month<=date('m');$month++)
{
$years[$current_year][] = $month_names[$month-1];
}

// Previous years
$years_to_create = $current_year - 2008;

if (!empty($years_to_create))
{
    for ($i = 1; $i <= $years_to_create; $i++)
    {
        $years[$current_year - $i] = $month_names;
    }
}

This seems a little simpler...is it any faster...?

Jack
Yes, it seems to be faster. 0.000255 0.000293 0.000291 = avrg 0.000279
DavidM
+1  A: 
$current_year = date('Y');
$month_names = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
$years[$current_year] = array_slice($month_names, 0, date('m'));

for ($i = 2008; $i < $current_year; $i++) {
   $years[$i] = $month_names;
}
Adam
is it faster than mine?
Jack