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\$
1
  • \$\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, 2016 at 21:15

1 Answer 1

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\$
2
  • \$\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\$ Sep 9, 2016 at 23:09
  • \$\begingroup\$ for loop is inside foreach, $monthDays[] = $date; would not work. \$\endgroup\$
    – xReprisal
    Sep 10, 2016 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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