Рано или късно всяка бизнес система трябва да знае дали дадена дата е работен ден. За заплатите са нужни работните дни и часове в месеца. Куриерът обещава „доставка до 2 работни дни“. Автоматичният отговор на офиса, напомнянето, срокът „до 14 работни дни“ и дори будилникът в умния дом зависят от същия въпрос. В България отговорът не е „от понеделник до петък минус един постоянен списък“: Великден се мести по православния календар, празниците през уикенда отиват на следващия работен ден, а правителството понякога обявява допълнителни почивни дни. Тук събираме правилата, даваме тестван PHP код и показваме къде обикновено се чупи ръчно писаният код.
#Официалните празници
Чл. 154, ал. 1 от Кодекса на труда изброява официалните празници:
- 1 януари, Нова година;
- 3 март, Ден на Освобождението на България от османско иго, националният празник;
- 1 май, Ден на труда и на международната работническа солидарност;
- 6 май, Гергьовден, Ден на храбростта и Българската армия;
- 24 май, Ден на светите братя Кирил и Методий, на българската азбука, просвета и култура и на славянската книжовност;
- 6 септември, Ден на Съединението;
- 22 септември, Ден на Независимостта на България;
- 24, 25 и 26 декември, Бъдни вечер и Рождество Христово;
- Разпети петък, Велика събота, Великден (неделя) и понеделник след него, по православния календар.
Същият член назовава и 1 ноември, Деня на народните будители, но само като неприсъствен ден за всички учебни заведения. За всички останали той е работен ден. Само това изключение вече чупи общ списък с почивни дни за офиса и за семейния календар.
#Православният Великден се мести всяка година
Четири от празниците зависят от православния Великден, който се смята по юлианския календар и обикновено е по-късно от католическия. През 2026 г. той е на 12 април, а през 2027 г. на 2 май. Вградената в PHP функция easter_date() дава католическата дата, затова не може да се ползва директно. Алгоритъмът на Меус за юлианския календар, отместен с 13 дни към григорианския, е кратък и точен за годините от 1900 до 2099:
function orthodox_easter(int $year): DateTimeImmutable
{
$a = $year % 4;
$b = $year % 7;
$c = $year % 19;
$d = (19 * $c + 15) % 30;
$e = (2 * $a + 4 * $b - $d + 34) % 7;
$month = intdiv($d + $e + 114, 31);
$day = ($d + $e + 114) % 31 + 1;
// Julian calendar date + 13 days = Gregorian date (valid 1900 to 2099).
return (new DateTimeImmutable(sprintf('%d-%02d-%02d', $year, $month, $day)))->modify('+13 days');
}
#Празник през уикенда се мести на следващия работен ден
Чл. 154, ал. 2 добавя правилото, което повечето код забравя: когато празник, различен от великденските, се падне в събота или неделя, първият работен ден след него е неприсъствен, тоест почивен. Два празника през уикенда дават два такива дни. Няколко примера:
- 24 май 2026 г. е неделя, затова понеделник, 25 май 2026 г., е почивен.
- 6 септември 2026 г. е неделя, затова понеделник, 7 септември, е почивен.
- 26 декември 2026 г. е събота, затова понеделник, 28 декември, е почивен.
- 25 и 26 декември 2027 г. са събота и неделя, затова понеделник, 27, и вторник, 28 декември 2027 г., са почивни.
- 1 май 2027 г. се пада на Велика събота, а следващият понеделник вече е Великден, затова допълнителният почивен ден е вторник, 4 май 2027 г. Същото се случи и през 2021 г.
Кодът по-долу първо добавя постоянните празници и великденските дни, а след това мести всеки празник от уикенда на следващия делничен ден, който още не е почивен. Обработката по реда на датите покрива и двойната Коледа, и съвпадението с Великден:
function bulgarian_days_off(int $year): array
{
$fixed = ['01-01', '03-03', '05-01', '05-06', '05-24', '09-06', '09-22', '12-24', '12-25', '12-26'];
$off = [];
foreach ($fixed as $md) {
$off["$year-$md"] = true;
}
$easter = orthodox_easter($year);
foreach (['-2 days', '-1 day', '+0 days', '+1 day'] as $shift) {
$off[$easter->modify($shift)->format('Y-m-d')] = true; // Good Friday to Easter Monday
}
// Art. 154(2): a holiday other than Easter on a Saturday or Sunday gives the next free weekday off.
foreach ($fixed as $md) {
$date = new DateTimeImmutable("$year-$md");
if ((int) $date->format('N') < 6) {
continue;
}
do {
$date = $date->modify('+1 day');
} while ((int) $date->format('N') >= 6 || isset($off[$date->format('Y-m-d')]));
$off[$date->format('Y-m-d')] = true;
}
ksort($off);
return array_keys($off);
}
function is_working_day(DateTimeImmutable $date, array $extraDaysOff = []): bool
{
$day = $date->format('Y-m-d');
return (int) $date->format('N') < 6
&& ! in_array($day, bulgarian_days_off((int) $date->format('Y')), true)
&& ! in_array($day, $extraDaysOff, true);
}
Сверихме го с публикуваните календари: като преместени почивни дни дава 26 май и 8 септември 2025 г., 25 май, 7 септември и 28 декември 2026 г., както и 4 май, 27 и 28 декември 2027 г. Според него декември 2026 г. има 20 работни дни, а 14 работни дни след петък, 18 декември 2026 г., е сряда, 13 януари 2027 г.
#Дни, които обявява правителството
Министерският съвет може да обяви допълнителни неприсъствени дни. За въвеждането на еврото обяви 31 декември 2025 г. и 2 януари 2026 г. Никоя формула не ги предвижда, затова функцията по-горе приема списък с допълнителни почивни дни. Дръжте този списък в настройките, а не в кода, така че който поддържа системата, да може да добави деня в седмицата, в която е обявен. В същия списък е мястото и на фирмените ви почивни дни.
#Часове в месеца и срокове
Две изчисления има в почти всяка българска бизнес система:
- Работните часове в месеца: работните дни, умножени по продължителността на работния ден, обикновено 8 часа. Декември 2026 г. дава 20 × 8 = 160 часа. Те трябват за часовата ставка и извънредния труд.
- Срок в работни дни: вървете напред ден по ден и броете само работните дни, както в примера по-горе. Никога не добавяйте календарни дни, за да „поправите уикендите“ след това; така пропускате празниците по средата на периода.
Пазете входните данни, например списъка с допълнителни почивни дни, до резултата. Когато през март някой попита защо срокът е определен така през януари, ще можете да отговорите.
#Къде обикновено се чупи ръчно писаният код
- Католически Великден от
easter_date()вместо православен. - Няма преместени почивни дни или има само един, когато се срещнат два празника през уикенда.
- Местят се и великденските празници, които Кодексът на труда изключва.
- 1 ноември е почивен за всички или пък е забравен за училищата.
- Твърд списък за една година, който никой не обновява през януари.
- Часови зони: сървър с UTC решава кое е „днес“ два или три часа преди София.
#Същите правила в Home Assistant
Написахме тези правила още веднъж за умни домове и малки офиси, които ползват Home Assistant: Sedmitsa е интеграция, която знае празниците по Кодекса на труда с православния Великден, преместените почивни дни и обявените дни при въвеждането на еврото. Всеки добавен календар дава сензори за работен ден днес и утре, вида на деня, следващия почивен ден с дължината на цялата почивка, следващия работен ден и работните дни и часове в месеца. Календарен обект показва всеки празник. Изберете група класове и получавате и сензори за учебен ден и училищния календар за 2026/2027 г. по заповедта на министъра на образованието. Три действия отговарят на скриптове: проверка на дата, брой работни дни и дата след определен брой работни дни. Собствените почивни дни и работната събота са настройки, а не код.
Работи локално, без облачна услуга и без акаунт. Нейните 132 автоматични теста вървят в Home Assistant Core 2026.10.0, а правилата за празниците са сверени с публикуваните български календари за 2021 до 2027 г. Sedmitsa е обявена като „Очаквайте скоро“.
#Често задавани въпроси
Ако празник се падне в събота, почивен ли е петъкът преди него?
Не. По чл. 154, ал. 2 от Кодекса на труда почивният ден се мести напред, към първия работен ден след празника, обикновено понеделник.
Местят ли се и великденските празници?
Не. Разпети петък, Велика събота, Великден и понеделникът след него са изключени от правилото. Велика събота и Великден никога не дават допълнителен почивен ден.
Почивен ли е 1 ноември?
Не и за работещите по принцип. Кодексът на труда го прави неприсъствен ден само за учебните заведения, затова училищният календар го третира различно от календара на офиса.
Как да се справя с ден, който правителството обяви по-късно?
Пазете списък с допълнителни почивни дни в настройките и добавете деня веднага щом решението бъде обнародвано. Никой алгоритъм не може да ги предвиди.
Коментари
Коментари
Напишете първия коментар.
Оставете коментар