| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > PHP: Общие вопросы > Посчитать количество рабочих дней |
| Автор: Gold Dragon 12.1.2014, 16:48 |
| Есть дата договора. Есть количество дней (рабочих) на исполнение, т.е. без субботы и воскресенья. Как минимальными затратами вычислить дату окончания договора? |
| Автор: baldina 12.1.2014, 20:31 |
| в предположении, что дата договора попадает на рабочий день недели <остаток>=<рабочих дней>%5 <дней всего>=7*<рабочих дней>/5+<остаток>+max(0,<остаток>?<день недели даты договора>-3:0) |
| Автор: Gold Dragon 12.1.2014, 20:49 |
| если честно, то ничего не понял. И мне не нужны проценты вероятности. мне нужна точная дата (государственные праздники не в счёт). Запросов должно быть много, так что код должен быть оптимизированный... ps может есть какая готовая функция? что-то я не нашёл |
| Автор: ksnk 12.1.2014, 21:12 |
| Разумнее, imho, вести базу нерабочих дней. То есть каждая запись в базе выглядит {день:XXX}. В базу попадаю все выходные и праздничные дни. Из базы выкидываются все рабочие дни и дни переноса "праздников". Заполняются вручную + полуавтомат про выходные. Сама табличка не особенно большая, к тому же ее можно чистить от устаревших данных. Для небольшого временнОго периода (неделя?), можно вычислять рабочие дни перебирая дни в цикле. Проверка - есть ли день в базе, если нету, значит рабочий. Для длинного диапазона - считаем, что от начальной даты должно пройти 7/5 дней от количества рабочих. Получаем диапазон. Выкидываем оттуда количество всех праздничных дней, из базы. получаем количество рабочих дней. Если рабочих дней нужно меньше или больше - отнимаем или прибавляем рабочие дни, как в первом случае. |
| Автор: Gold Dragon 12.1.2014, 21:37 |
| с базой не самый оптимальный вариант, но зато можно предусмотреть все праздники.. Нужно прикинуть... я так понимаю, мне нужно посчитать количество недель и добавить по 2 дня для каждой недели. Плюсь сделать поправку на полную неделю, т.е. начало и конец |
| Автор: Gold Dragon 12.1.2014, 23:17 |
| baldina, так если бы ты кодом писал сразу, а то алгоритмами.. вот и гадай что такое %5 а за разжевал +1 а вот по базе вопрос.. Мне необходимо "пробежаться" по базе договоров, допустим их порядка 500-1000 и высчитать просрочку.. Не сильно ли это подвисать будет? Хотя если кеш умный сделать... |
| Автор: baldina 12.1.2014, 23:26 | ||
1000 это очень, очень немного... Да и не нужна по 1000 договоров такая инфа, максимум по одному. Либо это некий отчет, а отчеты могут генериться не мгновенно, это нормально. Добавлено через 3 минуты и 4 секунды кстати. те же подсчеты можно прямо в запросе к базе проводить. и что-то мне подсказывает, что они будут быстрее php... и медленнее join таблицы праздников. |
| Автор: Gold Dragon 12.1.2014, 23:44 | ||
В общем нужно скорость проверять в реальных условиях... |
| Автор: maxipub 13.1.2014, 14:04 | ||
| Получаем timestamp начальной даты, и в цикле прибавляем к нему 86400, пока не дойдем до конечной даты, инкрементируя счетчик рабочих дней, где date('w', $timestamp) не 0, и не 6 (вс=0, сб=6). Может быть не минимальные затраты, но все же 5-6 строй кода. Да и корректней будет считать. ЗЫ: лет 10 сижу на форуме, всегда только спрашивал, что это сегодня решил ответить? Добавлено через 2 минуты и 23 секунды
0.05 сек, не более |
| Автор: Fortop 13.1.2014, 15:03 | ||
В таком духе лучше не отвечать |
| Автор: Gold Dragon 23.1.2014, 21:42 |
| baldina, что-то твой код не хочет рабоать.. уже устал его ломать например, задаю даты с шагом один день, получаю в два. Или задаю нчало договора в выходной, вообще как-то странно считает |
| Автор: baldina 24.1.2014, 13:34 | ||
дата договора за день считается: договор может закончиться в тот же день, но не раньше. если надо можешь вычесть 1 http://ideone.com/Ao5zCk |
| Автор: Gold Dragon 24.1.2014, 13:43 | ||||||||
а если так
то дата окончания
А это выходные PS выходные - рассматриваем только субботу и воскресенье Добавлено через 3 минуты и 22 секунды а если так
то имеем
|
| Автор: capitan 24.1.2014, 14:35 | ||
Была подобная задача. Показывать дату доставки учитывая выходные, праздники + смещение.
|
| Автор: Gold Dragon 24.1.2014, 14:38 |
| так это перебор получается? |
| Автор: capitan 24.1.2014, 14:43 | ||
А чем не устраивает? У вас где данные лежат по датам договоров и сроках? Если в базе, тогда просто в таблицу добавляем поле, где пишем дату окончания договора. При заполнении, считаем и пишем. Какие проблемы? Зато считаем все точно, учитывая все, что угодно. |
| Автор: Gold Dragon 24.1.2014, 15:03 | ||
| capitan, так проблем нет с перебором я написал для себя это: (вырезал из кода, т.ч. три метода)
в условие можно и праздники впихнуть смело. Гонял код, вроде всё корректно отдаёт. PS Код скорее всего не будет работать PHP 5 < 5.3.0 |
| Автор: capitan 24.1.2014, 15:18 |
| Каждую задачу нужно рассматривать с позиции целесообразности |
| Автор: Gold Dragon 24.1.2014, 15:20 | ||
|
| Автор: capitan 24.1.2014, 16:52 | ||
Нужно тестить, поидее должно работать:
|
| Автор: Gold Dragon 24.1.2014, 19:43 | ||
Это
выдаёт 20.01.2014, хотя должно 17-е |
| Автор: ksnk 24.1.2014, 21:25 | ||
а так?
P.S. слегка отформатировал и добавил 2013 год |
| Автор: ksnk 25.1.2014, 11:43 |
| Если в моем коде заменить strtotime('+1 day'... на +=60*60*24, и поменять ключики массива праздников на их числовые значения с выкидыванием формирования ключа, то работать будет в 4 раза быстрее. Вообще, о чем такая задача? На своей машинке - ноутбук с i3, 1000 200-дневных периодов посчиталось за 7 сек (исходно опубликованный - 30 сек). Как показывает практика - сервера (в моей доступности) решают такие задачи в 5-10 раз быстрее. Может быть и хватит скорости? |
| Автор: capitan 25.1.2014, 16:10 | ||||||||
не учел последние выхи на неделе. Делаем так: строку:
меняем на:
Теперь должно работать. |
| Автор: baldina 28.1.2014, 19:53 |
| Gold Dragon, если учитывать все обстоятельства, то как-то так http://ideone.com/mIyRNv Добавлено через 1 минуту и 3 секунды с базой попроще будет ;-) |
| Автор: Gold Dragon 29.1.2014, 08:19 | ||
| протестировал малость.. Тест:
мой код: 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 Вот вам и проблемы перебора.. Осталось проверить правильность Добавлено через 12 минут и 41 секунду baldina, 2014-01-04 10 дней всё таки 17.01 а не 20.01 |
| Автор: baldina 29.1.2014, 09:46 |
ну ты уж определись, считать или нет день даты договора |
| Автор: Gold Dragon 29.1.2014, 09:56 |
| ну вообще-то нет. "Шесть частей, но пять распилов" 1 2 3 4 5 3---4---5---6---7---8 |
| Автор: baldina 29.1.2014, 12:08 |
| ну тады вычти один день. сможешь? ;-) |
| Автор: Gold Dragon 29.1.2014, 12:12 |
| что-то совсем запутался.. в других вариантах правильно считает.. видимо перекос если начало суббота или воскресенье.. |
| Автор: baldina 29.1.2014, 12:13 | ||
Добавлено @ 12:13 http://ideone.com/IHqHPV Добавлено @ 12:14 т.е. двигаем не на пн а на предыдущую пт |
| Автор: baldina 29.1.2014, 12:58 | ||
наврал
http://ideone.com/cSskNE |