1
\$\begingroup\$

I'm creating an array of dates that won't be selectable in a calendar. The following works, although the way I've gone about it is quite long-winded.

I was wondering if there is a more elegant way of getting all the dates in a month, where dates don't fall on various days a project does run on. It's probably more clear from the example...

$project_days_this_month = []; 
$month_array = [];

$month = date('n'); 
$year = date('Y'); 

$project_days = [1, 6]; // days of week the project runs on
$days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, $year);     

// create an array of days in month
for ($day = 1; $day <= $days_in_month; $day++) {
  $date = $year.'-'.$month.'-'.$day; //format date
  $month_array[] = $date;
}

// get project days in month
foreach ($project_days as $pd) {
  //loop through all days
  for ($day = 1; $day <= $days_in_month; $day++) {

    $date = $year.'-'.$month.'-'.$day; //format date
    $day_number_of_week = date('N', strtotime($date)); 

    // add project days to array
    if($day_number_of_week == $pd){
        $project_days_this_month[] = $date;
    }

  }
}

// get the difference - these will be non project days  
$non_project_days = array_diff($month_array, $project_days_this_month);
print_r($non_project_days);

Are there any PHP functions that can be used here that would might make this code more concise?

\$\endgroup\$
  • \$\begingroup\$ Not really a code review type of question and can't really review when the pertinent code for cal_days_in_month() is not shown. You should familiarize yourself with PHP's DateTime, DatePeriod, DateInterval, etc. classes. \$\endgroup\$ – Mike Brant Sep 9 '16 at 21:15
1
\$\begingroup\$

My attempt to make this code as clean as possible. Note that i have not changed almost any of the logic you provided.

<?php

class ProjectDays {
    private $projectDays;

    public function __construct(array $projectDays, $month, $year) {
        $this->projectDays = $projectDays;
        $this->month = $month;
        $this->year = $year;
    }

    public function getNonProjectDays() {
        $monthDays = array();
        $projectDays = array();
        $daysInMonth = $this->getDaysInMonth();
        foreach ($this->projectDays as $projectDay) {
            for ($day = 1; $day <= $daysInMonth; $day++) {
                $date = $this->formatDate($day);
                $monthDays[$day] = $date;
                $weekDay = $this->getWeekDay($date);
                if($weekDay == $projectDay){
                    $projectDays[] = $date;
                }
            }
        }
        return array_diff($monthDays, $projectDays);
    }

    private function getWeekDay($date) {
        return date('N', strtotime($date));
    }

    private function getDaysInMonth() {
        return cal_days_in_month(CAL_GREGORIAN, $this->month, $this->year);
    }

    private function formatDate($day) {
        return "{$this->year}-{$this->month}-{$day}";
    }
}

$excludedDays = new ProjectDays([1, 6], date('n'), date('Y'));

print_r($excludedDays->getNonProjectDays());
\$\endgroup\$
  • \$\begingroup\$ It's beautiful , but can I ask, what is the purpose of $day in $monthDays[$day] = $date;? Wouldn't it work with $monthDays[] = $date; especially since the array index starts with 1 in the for loop, and not 0. \$\endgroup\$ – user3442612 Sep 9 '16 at 23:09
  • \$\begingroup\$ for loop is inside foreach, $monthDays[] = $date; would not work. \$\endgroup\$ – xReprisal Sep 10 '16 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.