Publikované 29. 11. 2019

Zistenie počtu pracovných dní a sviatkov v mesiaci

Jednoduchá PHP funkcia na zistenie počtu pracovných dní v mesiaci a dní pracovného voľna na Slovensku. Použitá napr. na mzdovej kalkulačke.

Úpravou zoznamu sviatkov v premennej $holidays možno použiť pre ďalšie krajiny. Napr. v Českej republike nie je sviatkom Veľký piatok, avšak navyše sú sviatky napr. 6.7 (upálenie Jána Husa), 28.9 (Deň Českej štátnosti) a 28.10 (Deň vzniku samostatného Československého štátu 1918).

Pre kontrolu správnosti môžete porovnať aktuálny prehľad štátnych sviatkov a dní pracovného pokoja.

Vyberte mesiac:

/**
* Helper class to find the number of workdays & the number of holidays
* in a given month in Slovak republic
*/
class CalendarUtils
{
	// list of state holidays + days off
	// https://www.vlada.gov.sk/slovensko/statne-sviatky/
	protected static $holidays = [
		// dates in format "d.m" (no zeroes, no trailing dot)
		'1.1',
		'6.1',
		//'19.4', // changes each year - easter friday
		//'22.4', // changes each year - easter monday
		'1.5',
		'8.5', // zruseny v 2025-2026, potom znovu plati - konsolidacia
		'5.7',
		'29.8',
		'1.9', // zruseny natrvalo od 24.03.2024
		'15.9', // zruseny v 2025-2026, potom znovu plati - konsolidacia
		'1.11',
		'17.11', // zruseny natrvalo od 1.11.2025 - https://www.relia.sk/Article.aspx?ID=1324
		'24.12',
		'25.12',
		'26.12',
	];

	/**
	* Vrati pocet prac. dni pre datumy OD - DO
	* @param int|string $dateFrom Date or timestamp
	* @param int|string $dateTo Date or timestamp
	* @return array($cntWorkday, $cntHoliday, $cntWeekend, $days)
	*/
	public static function countWorkdaysFromToSk($dateFrom, $dateTo)
	{
		$tsFrom = is_numeric($dateFrom) ? intval($dateFrom) : strtotime($dateFrom);
		$tsTo = is_numeric($dateTo) ? intval($dateTo) : strtotime($dateTo);

		if(!$tsFrom || !checkdate(date('n', $tsFrom), date('j', $tsFrom), date('Y', $tsFrom))){
			throw new CHttpException(500, 'Neplatný dátum od "'.$dateFrom.'".');
		}

		if(!$tsTo || !checkdate(date('n', $tsTo), date('j', $tsTo), date('Y', $tsTo))){
			throw new CHttpException(500, 'Neplatný dátum od "'.$dateTo.'".');
		}

		// add 23:59:59 for last day
		$tsTo = mktime(23,59,59,date('n', $tsTo), date('j', $tsTo), date('Y', $tsTo));
		$cntWorkday = $cntHoliday = $cntWeekend = 0;
		$days = [];

		for($ts = $tsFrom; $ts < $tsTo; $ts += 86400){
			$day = date('Y-m-d', $ts);
			$dayInWeek = date('N', $ts); // 1 = monday, 6 = saturday, 7 = sunday
			if($dayInWeek > 5){
				++$cntWeekend;
				$days[$day] = 'weekend';
			}elseif(self::isHoliday($ts)){
				++$cntHoliday;
				$days[$day] = 'holiday';
			}else{
				++$cntWorkday;
				$days[$day] = 'workday';
			}
		}

		return [$cntWorkday, $cntHoliday, $cntWeekend, $days];
	}

	/**
	* Return the number of work days and holidays
	* @param int $month
	* @param int $year
	* @return array($cntWorkDays, $cntHolidays)
	*/
	public static function countWorkdaysAndHolidaysInMonthSk($month, $year)
	{
		$month = intval($month);
		$year = intval($year);

		if($month < 1 || $month > 12){
			throw new \Exception('Invalid month ['.$month.'].');
		}
		if($year < 1900 || $year > 2050){
			throw new \Exception('Invalid year ['.$year.'].');
		}

		$ts = mktime(0,0,0,$month,1,$year);

		$daysInMonth = date('t', $ts); // 28 - 31
		$cntWorkDays = 0;
		$cntHolidays = 0;
		$days = [];

		for($day = 1; $day <= $daysInMonth; ++$day){

			$ts = mktime(0,0,0, $month, $day, $year);
			$dayInWeek = date('N', $ts); // 1 = monday, 7 = sunday

			if($dayInWeek > 5){
				$days[$day] = 'weekend';
				continue;
			}

			if(self::isHoliday($ts)){
				$days[$day] = 'holiday';
				++$cntHolidays;
			}else{
				$days[$day] = 'work';
				++$cntWorkDays;
			}
		}

		return [$cntWorkDays, $cntHolidays, $days];
	}

	/**
	* Return TRUE is supplied timestamp is a holiday
	* @param int $ts
	*/
	protected static function isHoliday($ts)
	{
		$dayMonth = date('j.n', $ts);
		$year = (int) date('Y', $ts);

		// je to sviatok z tabulky?
		if (in_array($dayMonth, self::$holidays, true)) {
			// vynimky / exceptions
			if ('1.9' == $dayMonth && $year >= 2024) {
				return false; // zruseny od / cancelled since 24.03.2024
			} elseif ('17.11' == $dayMonth && $year >= 2025) {
				return false; // zruseny od 1.11.2025
			} elseif (in_array($dayMonth,['8.5', '15.9']) && in_array($year, [2025, 2026])) {
				return false; // zrusene v 2025-2026, potom znovu platia (konsolidacia)
			}
			return true;
		}

		// vypocet velkej noci - algoritmus
		// https://sk.wikipedia.org/wiki/V%C3%BDpo%C4%8Det_d%C3%A1tumu_Ve%C4%BEkej_noci
		// https://en.wikipedia.org/wiki/Computus
		$easterTs = easter_date($year); // nedela

		// velky piatok
		$checkTs = strtotime('-2 day', $easterTs); // nedela minus dva dni
		if (date('j.n.Y', $checkTs) == date('j.n.Y', $ts)) {
			return true;
		}

		// velkonocny pondelok
		$checkTs = strtotime('+1 day', $easterTs); // nedela + jeden den
		if (date('j.n.Y', $checkTs) == date('j.n.Y', $ts)) {
			return true;
		}

		return false;
	}

}

Máte otázku?

Synet.sk

Profesionálna tvorba webových aplikácií a riešení na mieru. Konzultačné služby.

Demo

Kontakt


https://synet.sk