vincent vincent - 5 months ago 16
PHP Question

getting all months between 2 dates

I created a function that returns an array containing each month, starting from a supplied carbon date and ending on the current date.

Although the function is doing what it is supposed to do, it looks hideous. Clearly my programming skills arent yet what they're supposed to be. Surely there must be a better way to achieve what i want.

My code looks like this:

class DateUtilities {
protected $months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];

public function getMonthListFromDate(Carbon $date)
{
$monthArray = array();
$today = Carbon::today();

$currentYear = $today->copy()->format('Y');
$currentMonth = strtolower($today->copy()->format('F'));

$startYear = $date->copy()->format('Y');
$startMonth = strtolower($date->copy()->format('F'));

for($i = $startYear; $i <= $currentYear; $i ++) {
foreach($this->months as $monthIndex => $month) {
if (($monthIndex >= array_search($startMonth, $this->months) && $i == $startYear) ||
($monthIndex <= array_search($currentMonth, $this->months) && $i == $currentYear) ||
($i != $startYear && $i != $currentYear)) {
$formattedMonthIndex = ($monthIndex + 1);

if($formattedMonthIndex < 10) {
$monthArray['0' . $formattedMonthIndex . '-' . $i] = $month . ' ' . $i;
} else {
$monthArray[$formattedMonthIndex . '-' . $i] = $month . ' ' . $i;
}
}
}
}

return $monthArray;
}
}


and the result is:

array:25 [▼
"03-2013" => "march 2013"
"04-2013" => "april 2013"
"05-2013" => "may 2013"
"06-2013" => "june 2013"
"07-2013" => "july 2013"
"08-2013" => "august 2013"
"09-2013" => "september 2013"
"10-2013" => "october 2013"
"11-2013" => "november 2013"
"12-2013" => "december 2013"
"01-2014" => "january 2014"
"02-2014" => "february 2014"
"03-2014" => "march 2014"
"04-2014" => "april 2014"
"05-2014" => "may 2014"
"06-2014" => "june 2014"
"07-2014" => "july 2014"
"08-2014" => "august 2014"
"09-2014" => "september 2014"
"10-2014" => "october 2014"
"11-2014" => "november 2014"
"12-2014" => "december 2014"
"01-2015" => "january 2015"
"02-2015" => "february 2015"
"03-2015" => "march 2015"
]


Can anyone help me improve this code?

EDIT:

After the great tips i ended up with the following:

class DateUtilities {

public function getMonthListFromDate(Carbon $start)
{
$start = $start->startOfMonth();
$end = Carbon::today()->startOfMonth();

do
{
$months[$start->format('m-Y')] = $start->format('F Y');
} while ($start->addMonth() <= $end);

return $months;
}


}

Thank you for the help guys!!

Answer

With DateTime this could be easily achieved.

  1. Create a datetime object for each start and end date
  2. Setup an interval of 1 month
  3. Get a set of date beetween the start date and the end date with 1 month interval

Example :

public function getMonthListFromDate(Carbon $date)
{
    $start    = new DateTime(); // Today date
    $end      = new DateTime($date->toDateTimeString()); // Create a datetime object from your Carbon object
    $interval = DateInterval::createFromDateString('1 month'); // 1 month interval
    $period   = new DatePeriod($start, $interval, $end); // Get a set of date beetween the 2 period

    $months = array();

    foreach ($period as $dt) {
        $months[] = $dt->format("F Y");
    }

    return $months;
}

See it in action : http://3v4l.org/smS3N