Найти три предыдущих рабочих дня с указанной даты - PullRequest
6 голосов
/ 22 июня 2010

Мне нужно найти три предыдущих рабочих дня с указанной даты, исключая выходные и праздничные дни. Само по себе это не сложная задача, но, похоже, то, как я собирался это сделать, было бы слишком сложным, поэтому я решил сначала спросить ваше мнение.

Чтобы сделать вещи более интересными, давайте сделаем это соревнованием. Я предлагаю 300 в качестве награды тому, кто придумает самое короткое и чистое решение, соответствующее этой спецификации:

  • Напишите функцию, которая возвращает три предыдущих рабочих дня с указанной даты
  • Рабочий день определяется как любой день, который не является субботой или воскресеньем и не является выходным
  • Функция знает выходные дни года указанной даты и может учитывать их
  • Функция принимает один параметр - дату в формате Y-m-d
  • Функция возвращает массив с тремя датами в формате Y-m-d, отсортированный от самой старой к самой новой.

Дополнительно:

  • Функция может также найти следующие три рабочих дня в дополнение к предыдущим трем

Пример массива праздничных дней:

$holidays = array(
    '2010-01-01',
    '2010-01-06',
    '2010-04-02',
    '2010-04-04',
    '2010-04-05',
    '2010-05-01',
    '2010-05-13',
    '2010-05-23',
    '2010-06-26',
    '2010-11-06',
    '2010-12-06',
    '2010-12-25',
    '2010-12-26'
);

Обратите внимание, что в реальном сценарии праздники не жестко закодированы, а поступают из функции get_holidays($year). Вы можете включить / использовать это в своем ответе, если хотите.

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


Примечание

Если вы используете фиксированную продолжительность дня, например 86400 секунд, для перехода от дня к другому, у вас возникнут проблемы с переходом на летнее время. Вместо этого используйте strtotime('-1 day', $timestamp).

Пример этой проблемы:

http://codepad.org/uSYiIu5w


Окончательное решение

Вот окончательное решение, которое я в итоге использовал, адаптированное из идеи Кейта Минклера об использовании strtotime last weekday. Определяет направление по пройденному счету, если оно отрицательное, выполняет поиск в обратном направлении и вперед при положительном:

function working_days($date, $count) {

    $working_days = array();
    $direction    = $count < 0 ? 'last' : 'next';
    $holidays     = get_holidays(date("Y", strtotime($date)));

    while(count($working_days) < abs($count)) {
        $date = date("Y-m-d", strtotime("$direction weekday", strtotime($date)));
        if(!in_array($date, $holidays)) {
            $working_days[] = $date;
        }
    }

    sort($working_days);
    return $working_days;
}

Ответы [ 12 ]

0 голосов
/ 24 июня 2010

Попробуйте это (честное предупреждение - у меня нет доступа, чтобы проверить это, поэтому, пожалуйста, исправьте любые синтаксические ошибки).

function LastThreeWorkdays($start_date) { 
    $startdateseed = strtotime($start_date); 
    $workdays = array(); 
    $holidays = get_holidays('2010'); 

    for ($counter = -1; $counter >= -10; $counter--) 
      if (date('N', $current_date = strtotime($counter.' day', $startdateseed)) < 6) $workdays[] = date('Y-m-d', $currentdate);

    return array_slice(array_reverse(array_diff($workdays, $holidays)), 0, 3);
}

В основном создайте «кусок» дат, а затем используйте массив diff, чтобы удалить из него праздничные дни.Вернуть только верхние (последние) три предмета.Очевидно, что на вычисление уходит крошечно больше места и времени, чем в предыдущих ответах, но код намного короче.

Размер «куска» можно настроить для дальнейшей оптимизации.В идеале это будет максимальное количество последовательных праздников плюс 2 плюс 3, но это предполагает реалистичные сценарии праздников (целая неделя праздников невозможна и т. Д.)

Код можно «развернуть», чтобы некоторые трюки было легче читать.В целом некоторые функции PHP демонстрируются немного лучше - их можно комбинировать и с другими идеями.

0 голосов
/ 22 июня 2010

Вы имеете в виду, как функция WORKDAY () в Excel

Если вы посмотрите на функцию WORKDAYS в PHPExcel , вы найдете пример того, как закодировать такую ​​функцию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...