如何使用PHP将日期数组转换为3级嵌套列表

I have an array of dates in descending chronilogical order. As I loop through them, currently I am splitting up the string and using and comparing the current year & month to previous.

Here is the desired output (example):

<ul>
    <li><h1>2012</h1>
<ul>
<li><h2>Jan</h2>
    <ul>
    <li>Jan 1, 2012</li>
    <li>Jan 5, 2012</li>
    </ul>
</li>
<li><h2>Feb</h2>
    <ul>
    <li>Feb 3, 2012</li>
    <li>Feb 8, 2012</li>
    </ul>
</li>
</ul>
    </li>
    <li><h1>2011</h1>
<ul>
<li><h2>Jan</h2>
    <ul>
    <li>Jan 2, 2011</li>
    <li>Mar 2, 2011</li>
    </ul>
</li>
<li><h2>Feb</h2>
    <ul>
    <li>Feb 9, 2011</li>
    <li>Feb 20, 2011</li>
    </ul>
</li>
</ul>
    </li>
    </ul>

This is one of my attempts:

$archiveDateHTML = '<ul id="menu">';
$c = 0;

foreach ($ArchiveDates as $k=>$value){
$dateArray = split(' ', $value);

if($currentYear !== $dateArray[2] && $c+1 < count($ArchiveDates)){
    if($c > 0){ $archiveDateHTML .= '</ul>';}
    $archiveDateHTML .= '<h2 class="yearTitle">'.$dateArray[2].'</h2>';
    $archiveDateHTML .= '<ul class="yearList">';
    $newYear = 1;
}
if($currentMonth !== $dateArray[0] && $c+1 < count($ArchiveDates)){
    if($c > 0 && $newYear==0){ $archiveDateHTML .= '</ul>';}
    $archiveDateHTML .= '<h3 class="monthTitle">'.$dateArray[0].'</h3>';
    $archiveDateHTML .= '<ul class="monthList">';
    $newYear = 0;
}

$archiveDateHTML .= $value;

$currentYear = $dateArray[2];
$currentMonth = $dateArray[0];
$c++;
}
$archiveDateHTML .= '</ul>';

There is some obvious problems, with the above code. I keep getting so close, but can't quite wrap my head around the logic. Please assist and thank you so much!

Similar to paulgrav, this is my answer:

$dates = array(
  'Jan 1, 2012',
  'Jan 5, 2012',
  'Feb 3, 2012',
  'Feb 8, 2012',
  'Jan 2, 2011',
  'Mar 2, 2011',
  'Feb 9, 2011',
  'Feb 20, 2011');

$out = array();

foreach ($dates as $date) {
  list($m, $d, $y) = explode(" ", $date);
  $out[$y][$m][] = $date;
}

foreach ($out as $year => $group) {
  echo "<ul>
";
  echo "  <li><h1>$year</h1>
";
  echo "    <ul>
";
  foreach ($group as $month => $dates) {
    echo "    <li><h2>$month</h2>
";
    echo "      <ul>
";
    foreach ($dates as $date) {
      echo "        <li>$date</li>
";
    }
    echo "      </ul>
";
    echo "    </li>
";
  }
  echo "    </ul>
";
  echo "  </li>
";
  echo "</ul>
";
}

OUTPUT

<ul>
  <li><h1>2012</h1>
    <ul>
    <li><h2>Jan</h2>
      <ul>
        <li>Jan 1, 2012</li>
        <li>Jan 5, 2012</li>
      </ul>
    </li>
    <li><h2>Feb</h2>
      <ul>
        <li>Feb 3, 2012</li>
        <li>Feb 8, 2012</li>
      </ul>
    </li>
    </ul>
  </li>
</ul>
<ul>
  <li><h1>2011</h1>
    <ul>
    <li><h2>Jan</h2>
      <ul>
        <li>Jan 2, 2011</li>
      </ul>
    </li>
    <li><h2>Mar</h2>
      <ul>
        <li>Mar 2, 2011</li>
      </ul>
    </li>
    <li><h2>Feb</h2>
      <ul>
        <li>Feb 9, 2011</li>
        <li>Feb 20, 2011</li>
      </ul>
    </li>
    </ul>
  </li>
</ul>

Here’s how I would do it. Create your desired output data structure, then iterate over that to print out the ul/li elements.

Not sure the HTML is valid, but you should be able to easily fix that. When manipulating data in PHP it’s never a good idea to do both the manipulating and the output during the first iteration. It make your code a lot more complicated. Always try to breakdown the problem.

<?

$dates = array("2012 Jan 1","2012 Jan 2","2012 Feb 4");
$output = array();
foreach($dates as $date) {
    list($year, $month, $day) = split(' ', $date);
    $output[$year][$month][] = $day;
}

foreach($output as $year => $months) {
    print <<<HTML
    <ul>
    <li><h1>$year</h1>
<ul>
HTML;

    foreach($months as $month => $days) {
        print <<<HTML
        <li><h2>$month</h2>
    <ul>
HTML;

        print "<li>$month $day, $year</li>
";

    print <<<HTML
    </ul>
</li>
HTML;


    }

    print <<<HTML
    </ul>
    </li>
    </ul>
HTML;


}