Как стать автором
Обновить

Комментарии 42

эмм… А как учитывается тот факт, что у нас частенько переносятся празничные дни? типа «в субботу работаем за вторник»?
Эм…
1. А как это можно предсказать? Базовое, судя по описанию автора («При совпадении выходного и нерабочего праздничного дней выходной день переносится на следующий после праздничного рабочий день.») класс умеет, а что-то более сложное зависит от левых пяток управленцев. Или нет?
2. А в банках тоже часто произвольно переносят рабочие дни?
1. еще как зависит :)
2. если честно, не в курсе, думаю что они ориентируются на законы, а это п. 1

Но не думаю что ± 1 день может быть смертельно.
На постановления правительства. Лично я не полагаюсь на правило совпадающих праздников и выходных, а прописываю каждый перенос индивидуально. В этом году, ЕМНИП, уже был один «неправильный» перенос.

Не смертельно, конечно, но на бабло можно попасть серьёзно.
Угу, тоже встречался с решением ввиде таблицы Calendar, где для каждого дня прописывалось явно, рабочий он или не рабочий.

Ибо все это индивидуально. Да и прадзники чуть ли не каждый год меняются.
У меня смешанное решение: большинство праздников и выходных подхватываются автоматически (переносов праздников не бывает). Всё прописывается в 3 таблицы: (1) регулярные праздники в формате: ( дата, ( год начала, год конца) ), (2) даты искусственно будних и (3) искусственно выходных дней. Очень удобно.
Это возможно только вручную корректируя даты на каждый год. Так же здесь не обрабатываются исключения из правил, которые регулярно издаются.
Т. е. учитывается самое общее.
Ага, прошу прощения, не заметил строчку про совпадение выходных и праздников. В общем, спасибо, может пригодиться.
Отстой ваш класс, бегает по всем дням, делает для каждого дня нетривиальный и тяжелый вызов strtotime, а потом еще и не менее тяжелый date('w').

Вот вам функция, которая в константное время считает количество рабочих дней в интервале, не учитывая праздников. Остается прочекать для каждого праздника, 1) является ли он выходным и 2) входит ли в промежуток.

function workday_count($start_day_as_timestamp,$total_days)
{
    //$weekday 0 = Sun 1 = Mon ...   
    $weekday = date('w',$start_day_as_timestamp);   

    $days_without_1st_incomplete_week = $total_days — (7-$weekday);
    $workdays_in_1st_incomplete_week = 6 — $weekday;   

    $workdays_in_complete_weeks = floor($days_without_1st_incomplete_week / 7) * 5;   

    $days_in_last_week = $days_without_1st_incomplete_week % 7;
    $workdays_in_last_week = $days_in_last_week ? $days_in_last_week — 1: 0;   

    return $workdays_in_1st_incomplete_week + $workdays_in_complete_weeks + $workdays_in_last_week;
}


Дарю безвозмездно, ибо писал сие вчера, в ответ на не менее cтрашную функцию
Спасибо ) Всегда есть что оптимизировать :)
По идее надо делать скрипт, который бы парсил производственный календарь на текущий год, обновляемый на надежном сайте. Только вот что-то таких календарей в xml не выкладывают.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
да, бардак не автоматизируем…
НЛО прилетело и опубликовало эту надпись здесь
Это все понятно :)
В моем случае выглядит это как красный и зеленый цвет в списке исходящих счетов. Если что-то покраснеет или позеленеет раньше или позже на день, то ничего страшного в этом нет :)
ну скажем так. По закону каждый банк имеет право сам устанавливать продолжительность операционного дня. Скажем до 12:00 принимать платежки или до 15:00. А то что позже проводить следующим днем. Но в любом случае не позднее последнего пятого рейса 19:30 местного времени. Вроде так.
Бедные, а в Питере рейсов нет, и зачем они…
В банковских системах это решается с помощью отдельной таблицы операционных дней. Они автоматически генерятся на основе рабочего календаря (без суббот и воскресений) и потом каждый год корректируем руками добавляя/удаляя рабочии дни.
Может быть и Вам достаточно так же поступить?
Это самое гибкое решение.
А для справки можно посмотреть тут: www.calend.ru/work/ Там и про изменения написано.
Думаю что это самый правильный вариант.

желание автоматизировать и заставить систему работать без человеческого вмешательства меня погубит :)
Теперь понятно почему всё так плохо в банковской системе. Да потому, что софт написан на PHP.
а разве 31 декабря — банковский день?
да, банки работают. Некоторые просто закрываются раньше
НЛО прилетело и опубликовало эту надпись здесь
по законодательству — да,
да и по факту, в принципе, тоже
Нужно учесть, что есть еще и локальные праздники, которые объявляются нерабочим днем. В Чувашии, например, есть День Республики, 24 июня — нерабочий день. Думаю, подобные праздники есть и в других республиках.
Там в начале класса можно есть список праздников, туда можно дописать и 24е июня. Только один момент — точно ли этот праздник переносится при попадании на выходной день?
НЛО прилетело и опубликовало эту надпись здесь
А вам принципиально что это php, да?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Капец. Наколенная разработка людей, которые нифига не представляют себе финансы и бухучёт, которые только и умеют, что рисовать код и нахватались знаний про интерфейсы.
В какое место ни ткни — ни понимания о актах, счёт-фактурах, о кодах бюджетирования, когда в одном платеже по двум счетам оплачивают и много-много ещё о чём.

Это убогое поделище я уверен ещё смогут кому-то впарить!!! Но я с удовольствием посмотрю, как эта программа начнёт медленно катиться к реальным финансам компании и как будет наступать в головах разработчиков осознавание масштабности задачи.

Браво! Я в восхищении!!! Только от большого незнания можно вляпаться в ту задачу, которую вы себе поставили!!!
Господа, все комментарии по самой системе будут рады видеть в фидбеке на промо-сайте. А я, увы, оставлю вас без ответов.
Я всего лишь взял абстрактный класс и рассказал в каком контексте он мне понадобился :)
В конкретных регионах есть свои праздники, с которыми так же действуют правила переноса.

В Татарстане, например, таких три: Курбан-байрам (каждый год по-разному, по лунному календарю как-то считается), День независимости Татарстана (30 августа) и День конституции Татарстана (6 ноября).

И банки их соблюдают, даже филиалы общероссийских банков и иностранных.

Вообще идеально было бы, если б существовал какой-то официальный репозиторий с открытым API (как у ЦБ РФ с курсами валют).
попробую кинуть идею, а вы может заинтересуетесь и реализуете.

ваш класс решает три задачи. при этом задача номер три является частным случаем первой задачи.

3. узнать является ли ваш день банковским или нет, достаточно будет посчитать количество рабочих дней в промежутке от этого дня, до этого дня. Если 0 — то не банковский, если 1 — то банковский. Возможно не совсем корректно будет по производительности, но зато надежно. Ну либо в третьей задаче надо просто проверить на выходной, либо праздничный день :)

то есть остается две задачи.

1 задача —
я бы разбил на три класса, первый класс будет мне возващать количество выходных в определенный промежуток времени, второй класс будет возвращать количество праздников в определенный промежуток времени. А вот третий класс уже как нетрудно догадаться, будет возвращать банковские дни, при этом высчитать их легко, вычесть из общего количества дней выходные и данковские. Ну и подкорректировать границы с учетом заморочек какое время суток сейчас. Получиться более гибко и понятно.

2 задача — тут тоже ничего сложного. Берем левую границу, прибавляем N дней, высчитываем количество банковских дней, если оно меньше, чем то которое запросили, прибавляем еще разницу, и так пока у нас разница не превратится в 0. То есть в зависимости от того насколько длинный промежуток, получится три-четыре прохода наверное в среднем.

думаю должно получиться красивее, попробуйте.
промахнулся кнопкой ответ — ответ оказался ниже :)
Не очень понял идею в целом, но уточнение про время думаю может быть полезным. Т. е. если запрашивают дату 17.08.2009 18:03 + 2 дня то надо считать 18.08.200 + 2 дня ибо этот день уже прошел.
Хотя тут все зависит от типа входных данных — в некоторых случаях это может внести больше путаницы чем пользы, поэтому предлагаю всем желающим модифицировать под свои потребности :)
Но за идею спасибо.
А где исходник?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории