Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Посчитать количество рабочих дней 
:(
    Опции темы
Gold Dragon
Дата 12.1.2014, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Есть дата договора. Есть количество дней (рабочих) на исполнение, т.е. без субботы и воскресенья.

Как минимальными затратами вычислить дату окончания договора?


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



в предположении, что дата договора попадает на рабочий день недели
<остаток>=<рабочих дней>%5
<дней всего>=7*<рабочих дней>/5+<остаток>+max(0,<остаток>?<день недели даты договора>-3:0)

Это сообщение отредактировал(а) baldina - 12.1.2014, 20:38
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 20:49 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



если честно, то ничего не понял. И мне не нужны проценты вероятности. мне нужна точная дата (государственные праздники не в счёт).

Запросов должно быть много, так что код должен быть оптимизированный... 

ps
может есть какая готовая функция? что-то я не нашёл


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
ksnk
Дата 12.1.2014, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Разумнее, imho, вести базу нерабочих дней. То есть каждая запись в базе выглядит {день:XXX}. В базу попадаю все выходные и праздничные дни. Из базы выкидываются все рабочие дни и дни переноса "праздников". Заполняются вручную + полуавтомат про выходные. Сама табличка не особенно большая, к тому же ее можно чистить от устаревших данных.
Для небольшого временнОго периода (неделя?), можно вычислять рабочие дни перебирая дни в цикле. Проверка - есть ли день в базе, если нету, значит рабочий. 
Для длинного диапазона - считаем, что от начальной даты должно пройти 7/5 дней от количества рабочих. Получаем диапазон. Выкидываем оттуда количество всех праздничных дней, из базы. получаем количество рабочих дней. Если рабочих дней нужно меньше или больше - отнимаем или прибавляем рабочие дни, как в первом случае.



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Gold Dragon
Дата 12.1.2014, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



с базой не самый оптимальный вариант, но зато можно предусмотреть все праздники.. Нужно прикинуть...

я так понимаю, мне нужно посчитать количество недель и добавить по 2 дня для каждой недели. Плюсь сделать поправку на полную неделю, т.е. начало и конец


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 22:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  12.1.2014,  21:37 Найти цитируемый пост)
я так понимаю, мне нужно посчитать количество недель и добавить по 2 дня для каждой недели. Плюсь сделать поправку на полную неделю, т.е. начало и конец 

я тебе так и написал - как рассчитать число календарных дней. надеюсь по дате договора и числу дней ты в состоянии посчитать конечную дату. а ты про какие-то вероятности...

но вообще ksnk прав, если это реальная задача, праздники тоже надо учитывать. и база - самый разумный вариант. её размер будет невелик, так что скорость достаточно высока.

Добавлено @ 22:35
Код

function end_date ($start_date, $working_days) {
  $modulo = $working_days%5;
  $weekday = date ('N', $start_date);
  $days=7*(int)($working_days/5)+$modulo+max(0,$modulo?$weekday-3:0);
  return // $start_date + $days
}

разжевал. в рот сам положишь?  smile 

Это сообщение отредактировал(а) baldina - 12.1.2014, 22:59
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



baldina, так если бы ты кодом писал сразу, а то алгоритмами.. вот и гадай что такое %5  smile 
а за разжевал +1  smile 

а вот по базе вопрос.. Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку.. Не сильно ли это подвисать будет? Хотя если кеш умный сделать...

Это сообщение отредактировал(а) Gold Dragon - 12.1.2014, 23:20


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 12.1.2014, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  12.1.2014,  23:17 Найти цитируемый пост)
Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку

1000 это очень, очень немного...
Да и не нужна по 1000 договоров такая инфа, максимум по одному. Либо это некий отчет, а отчеты могут генериться не мгновенно, это нормально.

Добавлено через 3 минуты и 4 секунды
кстати. те же подсчеты можно прямо в запросе к базе проводить. и что-то мне подсказывает, что они будут быстрее php... и медленнее join таблицы праздников.
PM MAIL   Вверх
Gold Dragon
Дата 12.1.2014, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Цитата(baldina @  13.1.2014,  00:26 Найти цитируемый пост)
Либо это некий отчет, а отчеты могут генериться не мгновенно, это нормально.
Это типа корпоративный сайт, и это в том числе отчёты smile

В общем нужно скорость проверять в реальных условиях...



--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
maxipub
Дата 13.1.2014, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 517
Регистрация: 22.10.2009

Репутация: нет
Всего: 1



Получаем timestamp начальной даты, и в цикле прибавляем к нему 86400, пока не дойдем до конечной даты, инкрементируя счетчик рабочих дней, где date('w', $timestamp) не 0, и не 6 (вс=0, сб=6). Может быть не минимальные затраты, но все же 5-6 строй кода. Да и корректней будет считать.

ЗЫ: лет 10 сижу на форуме, всегда только спрашивал, что это сегодня решил ответить? smile  smile  smile

Добавлено через 2 минуты и 23 секунды
Цитата(Gold Dragon @  12.1.2014,  23:17 Найти цитируемый пост)
Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку..

0.05 сек, не более
PM MAIL   Вверх
Fortop
Дата 13.1.2014, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(maxipub @  13.1.2014,  14:04 Найти цитируемый пост)
 что это сегодня решил ответить? 


Цитата(maxipub @  13.1.2014,  14:04 Найти цитируемый пост)
Получаем timestamp начальной даты, и в цикле прибавляем к нему 86400, пока не дойдем до конечной даты

В таком духе лучше не отвечать smile


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Gold Dragon
Дата 23.1.2014, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



baldina, что-то твой код не хочет рабоать.. уже устал его ломать smile 
например, задаю даты с шагом один день, получаю в два. Или задаю нчало договора в выходной, вообще как-то странно считает


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 24.1.2014, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  23.1.2014,  21:42 Найти цитируемый пост)
задаю нчало договора в выходной


Цитата(baldina @  12.1.2014,  20:31 Найти цитируемый пост)
в предположении, что дата договора попадает на рабочий день недели


Цитата(Gold Dragon @  23.1.2014,  21:42 Найти цитируемый пост)
задаю даты с шагом один день, получаю в два

дата договора за день считается: договор может закончиться в тот же день, но не раньше. если надо можешь вычесть 1
http://ideone.com/Ao5zCk
PM MAIL   Вверх
Gold Dragon
Дата 24.1.2014, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



а если так
Код

$start_date = date_timestamp_get(date_create ('2014-01-01'));
for ($i=10; $i < 15; ++$i) {
echo date ('d/m/Y',end_date($start_date,$i)), PHP_EOL;
}

то дата окончания 
Цитата
...
18/01/2014
19/01/2014

А это выходные


PS
выходные - рассматриваем только субботу и воскресенье

Добавлено через 3 минуты и 22 секунды
а если так
Код

$start_date = date_timestamp_get(date_create ('2014-01-04'));
for ($i=10; $i < 15; ++$i) {
echo date ('d/m/Y',end_date($start_date,$i)), PHP_EOL;
}


то имеем
Цитата

18/01/2014 - сб
22/01/2014 - ср
23/01/2014 - чт
24/01/2014 - пт
25/01/2014 - сб


Это сообщение отредактировал(а) Gold Dragon - 24.1.2014, 13:43


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
capitan
Дата 24.1.2014, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Была подобная задача. Показывать дату доставки учитывая выходные, праздники + смещение.

Код

// Исходные данные
    define ('DELIV_SHIFT', 2) ; //смещение доставки ч + дней
    
    // Массив праздников. Ключ - месяц
    $holiday_days = array();
    $holiday_days[1] = array(1,2,3,4,5,6,7,8);
    $holiday_days[2] = array(23);
    $holiday_days[3] = array(8,10);
    $holiday_days[5] = array(1,9);
    $holiday_days[6] = array(12);
    $holiday_days[11] = array(3,4);
    
    
    $date=date("d.m.Y"); // Сегодня
    echo CheckHoliday($date, 0);
        
    function CheckHoliday($date, $count) {    
        global $holiday_days;
        
        $dayName = date('N', strtotime($date));
        $new_data = date("d.m.Y", strtotime($date ."+1 day"));    
                        
        if($dayName == 6 || $dayName == 7) {            
            return CheckHoliday($new_data, $count);
        } else {
            $check_day = date('j', strtotime($new_data));
            $check_month = date('n', strtotime($new_data));
            if(in_array($check_day, $holiday_days[$check_month])) {                    
                return CheckHoliday($new_data, $count);
            } else {
                if($count <= DELIV_SHIFT) {
                    $count +=1;
                    return CheckHoliday($new_data, $count);
                } else {
                    return $date;
                }
                
            }
        }        
    }


PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 24.1.2014, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



так это перебор получается?


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
capitan
Дата 24.1.2014, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Цитата(Gold Dragon @ 24.1.2014,  14:38)
так это перебор получается?

А чем не устраивает? У вас где данные лежат по датам договоров и сроках? Если в базе, тогда просто в таблицу добавляем поле, где пишем дату окончания договора. При заполнении, считаем и пишем. Какие проблемы? Зато считаем все точно, учитывая все, что угодно.

Это сообщение отредактировал(а) capitan - 24.1.2014, 14:43
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 24.1.2014, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



capitan, так проблем нет  smile просто я хотел что-то типа функции без перебора.. Я просто думаю что перебор всё же будет медленнее..

с перебором я написал для себя это: (вырезал из кода, т.ч. три метода)
Код

class LibDateTime
{
    /**
     * Возвращает конечную дату без учёта выходных
     *
     * @param string $date   : начальная дата
     * @param int    $days   : количество дней
     * @param string $format : формат возвращаемой даты
     *
     * @return string: дата окончания
     */
    public static function getEndDateWorking($date, $days, $format = 'd.m.Y')
    {
        while ($days) {
            $date = self::getDateAdd($date, 'P1D');
            if (self::formatDate($date, 'N') < 6) {
                $days--;
            }
        }
        return self::formatDate($date, $format);
    }

    /**
     * Прибавляет интервал к дате
     *
     * @param string $date     - дата
     * @param string $interval - интервал в формате ISO 8601, например, P5В (5 дней) или P3Y (3 года)
     *                         Y - Количество лет
     *                         M - Количество месяцев
     *                         D - Количество дней
     * @param string $format   - возвращаемый формат (по умолчанию  d.m.Y)
     *
     * @return string - дата в формате $format
     */
    public static function getDateAdd($date, $interval, $format = 'd.m.Y')
    {
        $d1 = new DateTime($date);
        $result = $d1->add(new DateInterval($interval))->format($format);
        return $result;
    }

    /**
     * Преобразует дату в нужный формат
     *
     * @param string $date   - дата
     * @param string $format - возвращаемый формат (по умолчанию  d.m.Y)
     *
     * @return string
     */
    public static function formatDate($date = '00.00.0000', $format = 'd.m.Y')
    {
        $date_obj = new DateTime($date);
        return $date_obj->format($format);
    }
}

 в условие можно и праздники впихнуть смело. Гонял код, вроде всё корректно отдаёт.

PS
Код скорее всего не будет работать PHP 5 < 5.3.0

Это сообщение отредактировал(а) Gold Dragon - 24.1.2014, 15:06


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
capitan
Дата 24.1.2014, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Каждую задачу нужно рассматривать с позиции целесообразности smile Если потом заказчик скажет, давай будем учитывать ещё и праздники, код полетит к чертям собачим. Я бы это учел сразу. Без учета праздников, учитывая только  сб и вск сделать можно и без перебора.
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 24.1.2014, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Цитата(capitan @  24.1.2014,  16:18 Найти цитируемый пост)
Без учета праздников, учитывая только  сб и вск сделать можно и без перебора. 
да вот не смог.. или дни вылетают или конечная дата приходится на выходной..



--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
capitan
Дата 24.1.2014, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Нужно тестить, поидее должно работать:
Код

    $date=date("d.m.Y"); // Сегодня
    echo CheckHolidayBeta($date, 33)."<br/>";

    function CheckHolidayBeta($date, $count) {

        $dayShift = date('N', strtotime($date));
        $count += $dayShift;

        $week_count = floor($count/5);
        $lastWeekDays = $week_count*7 - $dayShift + ($count % 5) + 1;

        $dateEnd = date("d.m.Y", strtotime($date ."+{$lastWeekDays} day"));
        $dateEndName = date('N', strtotime($dateEnd));
        $shiftEnd = ($dateEndName > 5) ? 7 - $dateEndName + 1 : 0;

        if(!empty($shiftEnd)) {
            echo date("d.m.Y", strtotime($dateEnd ."+{$shiftEnd} day"));
        } else {
            echo  $dateEnd;
        }
     }


Это сообщение отредактировал(а) capitan - 24.1.2014, 16:58
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 24.1.2014, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



Цитата(capitan @  24.1.2014,  17:52 Найти цитируемый пост)
Нужно тестить, поидее должно работать:

Это 
Код

echo CheckHolidayBeta('03.01.2014', 10);

выдаёт 20.01.2014, хотя должно 17-е

Это сообщение отредактировал(а) Gold Dragon - 24.1.2014, 19:44


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
ksnk
Дата 24.1.2014, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



а так?
Код

<?php
/**
 * class to hold all-around-calendar function
 */
class calendar
{

    /**
     * just a source; key - d/m/Y ; true==holiday, false==workdaay.
     * if absent - use weekday to consider
     * http://www.garant.ru/calendar/buhpravo/
     */
    private static $workdays = array(
//2013
        '01/01/2013' => true,
        '02/01/2013' => true,
        '03/01/2013' => true,
        '04/01/2013' => true,
        '07/01/2013' => true,
        '08/01/2013' => true,
        '08/03/2013' => true,
        '01/05/2013' => true,
        '02/05/2013' => true,
        '03/05/2013' => true,
        '09/05/2013' => true,
        '10/05/2013' => true,
        '12/06/2013' => true,
        '04/11/2013' => true,
// 2014
        '01/01/2014' => true,
        '02/01/2014' => true,
        '03/01/2014' => true,
        '06/01/2014' => true,
        '07/01/2014' => true,
        '08/01/2014' => true,
        '10/03/2014' => true,
        '01/05/2014' => true,
        '02/05/2014' => true,
        '09/05/2014' => true,
        '12/06/2014' => true,
        '03/11/2014' => true,
        '04/11/2014' => true,
    );

    /**
     * return day $workdays days after $day
     * @param string|int $day
     * @param int $workdays
     * @return int|string
     */
    static function addWorkDays($day, $workdays)
    {
        if (is_string($day)) {
            $day = strtotime($day);
        }
        while ($workdays > 0) {
            $day = strtotime('+1 day', $day);
            $key = date('d/m/Y', $day);
            if (isset(self::$workdays[$key])) {
                if (!self::$workdays[$key]) {
                    $workdays--;
                }
            } else {
                switch (date('w', $day)) {
                    case '0':
                    case '6':
                        break;
                    default:
                        $workdays--;
                }
            }
        }
        return $day;
    }
}

/**
 *  so let's test it
 */

echo date('d/m/Y', calendar::addWorkDays('01.01.2014', 10)) . "\n";
echo date('d/m/Y', calendar::addWorkDays('08.01.2014', 10)) . "\n";
echo date('d/m/Y', calendar::addWorkDays('01.01.2014', 8)) . "\n";
echo date('d/m/Y', calendar::addWorkDays('03.01.2014', 7)) . "\n";


P.S. слегка отформатировал и добавил 2013 год

Это сообщение отредактировал(а) ksnk - 24.1.2014, 22:03


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
ksnk
Дата 25.1.2014, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Если в моем коде заменить strtotime('+1 day'... на +=60*60*24, и  поменять ключики массива праздников на их числовые значения с выкидыванием формирования ключа, то работать будет в 4 раза быстрее.

Вообще, о чем такая задача? 
На своей машинке - ноутбук с i3, 1000 200-дневных периодов посчиталось за 7 сек (исходно опубликованный - 30 сек). Как показывает практика - сервера (в моей доступности) решают такие задачи в 5-10 раз быстрее. Может быть и хватит скорости?


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
capitan
Дата 25.1.2014, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 9
Всего: 13



Цитата(Gold Dragon @ 24.1.2014,  19:43)
Цитата(capitan @  24.1.2014,  17:52 Найти цитируемый пост)
Нужно тестить, поидее должно работать:

Это 
Код

echo CheckHolidayBeta('03.01.2014', 10);

выдаёт 20.01.2014, хотя должно 17-е

не учел последние выхи на неделе.
Делаем так:
строку:
Код

       $lastWeekDays = $week_count*7 - $dayShift + ($count % 5) + 1;


меняем на:
Код

        // Fix на последние выходные на неделе
        $fix_end = ( $count % 5 > 0 ) ? 0 : 2;
        $lastWeekDays = $week_count*7 - $dayShift + ($count % 5) - $fix_end;


Теперь должно работать.
PM MAIL WWW ICQ   Вверх
baldina
Дата 28.1.2014, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Gold Dragon, если учитывать все обстоятельства, то как-то так
http://ideone.com/mIyRNv

Добавлено через 1 минуту и 3 секунды
с базой попроще будет ;-)
PM MAIL   Вверх
Gold Dragon
Дата 29.1.2014, 08:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



протестировал малость..

Тест:
Код

$sysstart = microtime(true);
for($i = 0; $i < 250; $i++){
    LibDateTime::getEndDateWorking('12.01.2014', 50);
}
echo round((microtime(true) - $sysstart), 5). '<hr>';



мой код:

250 запросов 50 дней   - 3.78722
250 запросов 100 дней - 7.81845
500 запросов 50 дней   - 7.61444
500 запросов 100 дней - 15.58989

код baldina:

250 запросов 50 дней   - 0.016
250 запросов 100 дней - 0.011
500 запросов 50 дней   - 0.022
500 запросов 100 дней - 0.022

 smile 

Вот вам и проблемы перебора.. Осталось проверить правильность

Добавлено через 12 минут и 41 секунду
baldina, 2014-01-04 10 дней всё таки 17.01 а не 20.01


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 29.1.2014, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(Gold Dragon @  29.1.2014,  08:19 Найти цитируемый пост)
baldina, 2014-01-04 10 дней всё таки 17.01 а не 20.01 

ну ты уж определись, считать или нет день даты договора
PM MAIL   Вверх
Gold Dragon
Дата 29.1.2014, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



ну вообще-то нет. "Шесть частей, но пять распилов"

   1    2    3   4    5
3---4---5---6---7---8




--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 29.1.2014, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



ну тады вычти один день. сможешь? ;-)
PM MAIL   Вверх
Gold Dragon
Дата 29.1.2014, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 10
Всего: 71



что-то совсем запутался..  smile 
в других вариантах правильно считает.. видимо перекос если начало суббота или воскресенье..


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
baldina
Дата 29.1.2014, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Код

  if ($weekday > 4) {
    $start_date -= ONE_DAY*(6-$weekday);
    $weekday=4;
  }


Добавлено @ 12:13
http://ideone.com/IHqHPV

Добавлено @ 12:14
т.е. двигаем не на пн а на предыдущую пт


Это сообщение отредактировал(а) baldina - 29.1.2014, 12:18
PM MAIL   Вверх
baldina
Дата 29.1.2014, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



наврал
Код

$start_date -= ONE_DAY*($weekday-4);

http://ideone.com/cSskNE
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0828 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.