Вывести на PHP график работы, начиная с 1 числа

Подскажите, как вывести на PHP график работы, начиная с 1 числа сутки через двое. Причем, если день попадает на выходной, то переносим его на ближайший следующий понедельник и далее снова сутки через двое. Пробую так, но выводит то не с 1 числа то не 1 через 2, а 2 через 2.

function isWeekend($date) {
    return (date('N', strtotime($date)) >= 6);
}
function isWorkDay($num) {
    return ($num % 4) < 2;
}
for ($i = 0; $i < $days; $i++) {
    if (isWorkDay($i)) {
        echo $i . '+';
        echo PHP_EOL;
    } else {
        echo $i;
        echo PHP_EOL;
    }
}

Ответы (2 шт):

Автор решения: Егор Банин

Для начала решите задачу без учёта выходных. Сутки через двое это каждый третий день, каждый день кратный трём. Чтобы понять, что число кратно трём, надо взглянуть на остаток от деления на 3.

function isWorkDay($day int): bool {
    return $day % 3 === 0;
}

Теперь надо добавить выходные. Функцию проверки вы написали, но как ей воспользоваться, чтобы перенести рабочий день? Если рабочий день выпал на выходной, можно просто сбросить счётчик рабочих дней. Получается, что дни месяца и счётчик рабочих дней это не одна, а две переменные.

$fdm = new DateTimeImmutable('first day of this month midnight');
$workingDays = [];
$wDay = 0;
for ($day = 0; $day < $fdm->format('t'); ++$day) {
    if ($wDay % 3 === 0) {
        $d = $fdm->add(new DateInterval('P' . $day . 'D'));
        if ($d->format('N') < 6) { // будни
            $workingDays[] = $d;    
        } else { // выходные
            $wDay = 0;
            continue;
        }
    }

    ++$wDay;
}

var_dump($workingDays);
→ Ссылка
Автор решения: Tunker

Вообще график очень странный, кроме первой недели он всегда сводится к понедельнику и четвергу. Т.е. если график действительно по таким условиям, то в принципе вы можете проверять только первую неделю: Понедельник - Рабочие дни Понедельник и Четверг

Вторник - Вторник и Пятница

Среда, Четверг, Пятница - они же

далее каждая неделя Понедельник и Четверг

Если нужно решение в лоб, то код привел

<?php
$date_begin = '2022-09-23';
$days       = 20;

$datetime = DateTime::createFromFormat('Y-m-d', $date_begin);
$workday  = 2;
echo "date\ti\tday\twork" . PHP_EOL;
for ($i = 0; $i < $days; ++$i)
{
    ++$workday;
    if (date('N', strtotime($datetime->format('d-m-Y'))) < 6 and $workday > 2)
    {
        $workday = 0;
    }
    echo $datetime->format('d-m-Y') . "\t" . $i . "\t" . date('N', strtotime($datetime->format('d-m-Y')));
    if ($workday == 0)
        echo '+';
    echo PHP_EOL;
    $datetime->modify('+1 days');
}
→ Ссылка