Publikované 29. 11. 2019

Fond pracovného času v mesiaci - výpočet v PHP

Jednoduchá utilita počítajúca počet pracovných dní v mesiaci 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 naviac sviatky od Slovenska sú 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ť napr. s online kalendárom.

Vyberte mesiac:

/**
* Helper class to find the number of work days and the number of holidays in a given month in Slovakia
*/
class CalendarUtils
{
	// list of state holidays
	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',
		'5.7',
		'29.8',
		'1.9',
		'15.9',
		'1.11',
		'17.11',
		'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.'".');
		}

		$tsTo = mktime(23,59,59,date('n', $tsTo), date('j', $tsTo), date('Y', $tsTo)); // add 23:59:59 for last day
		$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)
	{
		// je to sviatok z tabulky?
		$dayMonth = date('j.n', $ts);
		if (in_array($dayMonth, self::$holidays)) {
			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
		$year = (int) date('Y', $ts);
		$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