RRule\RRule::buildWeeknoMask PHP Method

buildWeeknoMask() protected method

Because weeks can cross year boundaries (that is, week #1 can start the previous year, and week 52/53 can continue till the next year), the algorithm is quite long.
protected buildWeeknoMask ( integer $year, integer $month, integer $day, array &$masks ) : null
$year integer
$month integer
$day integer
$masks array
return null (modifies $mask)
    protected function buildWeeknoMask($year, $month, $day, array &$masks)
    {
        $masks['yearday_is_in_weekno'] = array();
        // calculate the index of the first wkst day of the year
        // 0 means the first day of the year is the wkst day (e.g. wkst is Monday and Jan 1st is a Monday)
        // n means there is n days before the first wkst day of the year.
        // if n >= 4, this is the first day of the year (even though it started the year before)
        $first_wkst = (7 - $masks['weekday_of_1st_yearday'] + $this->wkst) % 7;
        if ($first_wkst >= 4) {
            $first_wkst_offset = 0;
            // Number of days in the year, plus the days we got from last year.
            $nb_days = $masks['year_len'] + $masks['weekday_of_1st_yearday'] - $this->wkst;
            // $nb_days = $masks['year_len'] + pymod($masks['weekday_of_1st_yearday'] - $this->wkst,7);
        } else {
            $first_wkst_offset = $first_wkst;
            // Number of days in the year, minus the days we left in last year.
            $nb_days = $masks['year_len'] - $first_wkst;
        }
        $nb_weeks = (int) ($nb_days / 7) + (int) ($nb_days % 7 / 4);
        // alright now we now when the first week starts
        // and the number of weeks of the year
        // so we can generate a map of every yearday that are in the weeks
        // specified in byweekno
        foreach ($this->byweekno as $n) {
            if ($n < 0) {
                $n = $n + $nb_weeks + 1;
            }
            if ($n <= 0 || $n > $nb_weeks) {
                continue;
            }
            if ($n > 1) {
                $i = $first_wkst_offset + ($n - 1) * 7;
                if ($first_wkst_offset != $first_wkst) {
                    // if week #1 started the previous year
                    // realign the start of the week
                    $i = $i - (7 - $first_wkst);
                }
            } else {
                $i = $first_wkst_offset;
            }
            // now add 7 days into the resultset, stopping either at 7 or
            // if we reach wkst before (in the case of short first week of year)
            for ($j = 0; $j < 7; $j++) {
                $masks['yearday_is_in_weekno'][$i] = true;
                $i = $i + 1;
                if ($masks['yearday_to_weekday'][$i] == $this->wkst) {
                    break;
                }
            }
        }
        // if we asked for week #1, it's possible that the week #1 of next year
        // already started this year. Therefore we need to return also the matching
        // days of next year.
        if (in_array(1, $this->byweekno)) {
            // Check week number 1 of next year as well
            // TODO: Check -numweeks for next year.
            $i = $first_wkst_offset + $nb_weeks * 7;
            if ($first_wkst_offset != $first_wkst) {
                $i = $i - (7 - $first_wkst);
            }
            if ($i < $masks['year_len']) {
                // If week starts in next year, we don't care about it.
                for ($j = 0; $j < 7; $j++) {
                    $masks['yearday_is_in_weekno'][$i] = true;
                    $i += 1;
                    if ($masks['yearday_to_weekday'][$i] == $this->wkst) {
                        break;
                    }
                }
            }
        }
        if ($first_wkst_offset) {
            // Check last week number of last year as well.
            // If first_wkst_offset is 0, either the year started on week start,
            // or week number 1 got days from last year, so there are no
            // days from last year's last week number in this year.
            if (!in_array(-1, $this->byweekno)) {
                $weekday_of_1st_yearday = date_create($year - 1 . '-01-01 00:00:00')->format('N');
                $first_wkst_offset_last_year = (7 - $weekday_of_1st_yearday + $this->wkst) % 7;
                $last_year_len = 365 + is_leap_year($year - 1);
                if ($first_wkst_offset_last_year >= 4) {
                    $first_wkst_offset_last_year = 0;
                    $nb_weeks_last_year = 52 + (int) (($last_year_len + ($weekday_of_1st_yearday - $this->wkst) % 7) % 7 / 4);
                } else {
                    $nb_weeks_last_year = 52 + (int) (($masks['year_len'] - $first_wkst_offset) % 7 / 4);
                }
            } else {
                $nb_weeks_last_year = -1;
            }
            if (in_array($nb_weeks_last_year, $this->byweekno)) {
                for ($i = 0; $i < $first_wkst_offset; $i++) {
                    $masks['yearday_is_in_weekno'][$i] = true;
                }
            }
        }
    }