Ведение совокупного подсчета месяцев

Я хочу вести подсчет месяцев, встречающихся в датах, читать из CSV, где даты вводятся в формате дд / мм / гггг. $all это массив этих дат. Я наблюдаю за успеваемостью студентов в учебном году, который начинается в сентябре и заканчивается в июле. Дата представляет достижения студента. Мне нужно, чтобы подсчет был кумулятивным — дата в сентябре также должна учитываться во все последующие месяцы и т. Д. Затем я использую это для создания графика Google, такого как этот:

Пример графика

У меня есть следующий рабочий код, который кажется очень громоздким. Я чувствую, что мне не хватает чего-то, что позволило бы гораздо более краткий способ решения моей проблемы.

Существуют ли общие решения для работы с датами таким образом? Можете ли вы предложить более широкое чтение?

    foreach ($all as $y) {
$month = substr($y,3, 2);

switch ($month) {
case '09':
$sep++;$oct++;$nov++;$dec++;$jan++;$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '10':
$oct++;$nov++;$dec++;$jan++;$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '11':
$nov++;$dec++;$jan++;$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '12':
$dec++;$jan++;$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '01':
$jan++;$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '02':
$feb++;$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '03':
$mar++;$apr++;$may++;$jun++;$jul++;
break;
case '04':
$apr++;$may++;$jun++;$jul++;
break;
case '05':
$may++;$jun++;$jul++;
break;
case '06':
$jun++;$jul++;
break;
case '07':
$jul++;
break;
default:
$jul++;
}

}

//All months initially set to 1 to help with scaling issues.
//Work out percentage of all achievements completed
$NOW  = date("n");
switch($NOW) {
case '9':
if ($sep != 1) {
$sep = round(($sep-1)/$total*100);
}
$oct="null";$nov="null";$dec="null";$jan="null";$feb="null";$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '10':
if ($oct != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
}
$nov="null";$dec="null";$jan="null";$feb="null";$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '11':
if ($nov != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
}
$dec="null";$jan="null";$feb="null";$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '12':
if ($dec != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
}
$jan="null";$feb="null";$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '1':
if ($jan != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
}
$feb="null";$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '2':
if ($feb != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
}
$mar="null";$apr="null";$may="null";$jun="null";$jul="null";
break;

case '3':
if ($mar != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
}
$apr="null";$may="null";$jun="null";$jul="null";
break;

case '4':
if ($apr != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
$apr = round(($apr-1)/$total*100);
}
$may="null";$jun="null";$jul="null";
break;

case '5':
if ($may != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
$apr = round(($apr-1)/$total*100);
$may = round(($may-1)/$total*100);
}
$jun="null";$jul="null";
break;

case '6':
if ($jun != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
$apr = round(($apr-1)/$total*100);
$may = round(($may-1)/$total*100);
$jun = round(($jun-1)/$total*100);
}
$jul="null";
break;

case '7':
if ($jul != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
$apr = round(($apr-1)/$total*100);
$may = round(($may-1)/$total*100);
$jun = round(($jun-1)/$total*100);
$jul = round(($jul-1)/$total*100);
}
break;

case '8':
if ($jul != 1) {
$sep = round(($sep-1)/$total*100);
$oct = round(($oct-1)/$total*100);
$nov = round(($nov-1)/$total*100);
$dec = round(($dec-1)/$total*100);
$jan = round(($jan-1)/$total*100);
$feb = round(($feb-1)/$total*100);
$mar = round(($mar-1)/$total*100);
$apr = round(($apr-1)/$total*100);
$may = round(($may-1)/$total*100);
$jun = round(($jun-1)/$total*100);
$jul = round(($jul-1)/$total*100);
}
break;

default:
echo " ";

}

1

Решение

Мое предложение не хранить накопленные данные, проще хранить реальное количество достижений в месяц. Вы можете сделать это, заполнив array чьи ключи месяцы (от 1 до 12):

$counts = array();
foreach ($all as $y) {
$month = (int)substr($y,3,2);

if (isset($counts[$month]))
$counts[$month] = 0;

$counts[$month]++;
}

РЕДАКТИРОВАТЬ

Теперь вы можете просто зацикливаться на $counts нормализовать каждую запись:

$total = array_sum($counts);
$sum = 0;

// Avoiding division by zero
if ($total != 0) {

foreach (array_merge(range(9,12),range(1,7)) as $key) {

$sum += $counts[$key];
$counts[$key] = round($sum/$total*100);

}

}
0

Другие решения

Вот решение, которое должно дать те же результаты:

// Work with month numbers relative to school year:
$cur_month  = (3 + date("n")) % 12; // 0 = september, 1 = october, ...

// Collect monthly statistics (August excluded)
$stats = array_fill(0, 11, 0);
foreach ($all as $date) {
// Extract month and transpose to school month: 0 = september, ...
$month = (3+substr($date,3, 2)) % 12;
// August is mapped to July
$month = min(11, $month);
// Only data in the past or current month is taken into account:
if ($month <= $cur_month) $stats[$month]++;
}

// Cumulate statistics:
$total = 0;
foreach ($stats as $month => &$stat) {
$total += $stat;
// Avoid zeroes for scaling problems
$stat = max(1, $total);
}

// Don't allow total == 0
$total = max(1, $total);

// Convert to percentages, and clear future months
foreach ($stats as $month => &$stat) {
$stat = $month <= $cur_month
? round($stat / $total * 100)
: 'null';
}

// Assign to individual variables, if needed
list($sep, $oct, $nov, $dec, $jan, $feb,
$mar, $apr, $may, $jun, $jul) = $stats;
0