У меня есть срок до 5 дней, мне нужно добавить +1 день для каждого нерабочего дня (выходные или праздничные дни)

0

Я пытаюсь сделать правило, где у меня есть срок, 5 дней мне нужно добавить +1 день для каждого нерабочего дня (выходные или праздничные дни). также праздники следующей таблицы, напоминающие, что если последний день не может быть выходным или праздничным днем ...

Мой праздничный день

Изображение 174551

Я пробовал это в любом случае, но я не могу получить хороший результат

//The function returns the no. of business days between two dates and it skips the holidays
function getWorkingDays($startDate,$endDate,$holidays){
    // do strtotime calculations just once
    $endDate = strtotime($endDate);
    $startDate = strtotime($startDate);


    //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
    //We add one to inlude both dates in the interval.
    $days = ($endDate - $startDate) / 86400 + 1;

    $no_full_weeks = floor($days / 7);
    $no_remaining_days = fmod($days, 7);

    //It will return 1 if it Monday,.. ,7 for Sunday
    $the_first_day_of_week = date("N", $startDate);
    $the_last_day_of_week = date("N", $endDate);

    //---->The two can be equal in leap years when february has 29 days, the equal sign is added here
    //In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
    if ($the_first_day_of_week <= $the_last_day_of_week) {
        if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week) $no_remaining_days--;
        if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week) $no_remaining_days--;
    }
    else {
        // (edit by Tokes to fix an edge case where the start day was a Sunday
        // and the end day was NOT a Saturday)

        // the day of the week for start is later than the day of the week for end
        if ($the_first_day_of_week == 7) {
            // if the start date is a Sunday, then we definitely subtract 1 day
            $no_remaining_days++;

            if ($the_last_day_of_week == 6) {
                // if the end date is a Saturday, then we subtract another day
                $no_remaining_days++;
            }
        }
        else {
            // the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
            // so we skip an entire weekend and subtract 2 days
            $no_remaining_days += 2;
        }
    }

    //The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
    //---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
   $workingDays = $no_full_weeks * 5;
    if ($no_remaining_days > 0 )
    {
      $workingDays += $no_remaining_days;
    }

    //We subtract the holidays
    foreach($holidays as $holiday){
        $time_stamp=strtotime($holiday->data);
        //If the holiday doesn't fall in weekend
        if ($startDate <= $time_stamp && date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7)
            $workingDays++;
    }

    return $workingDays;
}
Теги:

1 ответ

0
Лучший ответ

Используя DateTime и DateInterval вы можете добавить число рабочих дней к дате начала с дополнительным массивом праздников:

function getDeadline($start_date, $working_days, array $holiday_dates = array())
{
    $date = DateTime::createFromFormat('Y-m-d', $start_date);
    $interval = new DateInterval('P1D'); // one day
    $holiday_dates = array_flip($holiday_dates); // so we can use isset to check for holidays
    while (
        $date->format('N') >= 6 // weekend day
        || isset($holiday_dates[$date->format('Y-m-d')]) // OR holiday
        || $working_days-- > 0 // OR deadline working days left to add
    ) {
        $date->add($interval); // move to next day
    }
    return $date->format('Y-m-d');
}

Тестирование следующим образом:

var_dump(getDeadline('2017-12-21', 5)); // only weekends
var_dump(getDeadline('2017-12-21', 5, array('2017-12-22', '2017-12-26'))); // weekends and holidays

Дает выход:

string(10) "2017-12-28"
string(10) "2018-01-01"

Поскольку ваши праздники хранятся в mysql, вы можете использовать такую функцию, чтобы извлечь их в одном запросе:

function getHolidays($start_date)
{
    $database = new PDO(/* your connection details here */);
    $statement = $database->prepare("
        SELECT DISTINCT date
        FROM holiday
        WHERE date >= :start_date
        ORDER BY date ASC;
    ");
    $statement->bindValue(':start_date', $start_date);
    $statement->execute();
    return $statement->fetchAll(PDO::FETCH_COLUMN);
}

Предполагая, что таблица holidays существует, как в вашем вопросе, вы можете объединить эти функции, чтобы получить дату окончания:

$holidays = getHolidays('2017-12-21');
var_dump($holidays);
$deadline_end_date = getDeadline('2017-12-21', 5, $holidays);
var_dump($deadline_end_date);

Дает выход:

array(6) {
  [0]=>
  string(10) "2017-12-22"
  [1]=>
  string(10) "2017-12-26"
  [2]=>
  string(10) "2017-12-27"
  [3]=>
  string(10) "2018-01-01"
  [4]=>
  string(10) "2018-01-02"
  [5]=>
  string(10) "2018-01-03"
}
string(10) "2018-01-05"
  • 0
    Отлично! Ты был лучшим, я пробовал несколько дней! Отлично, отлично!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню