Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 88 |
| WorkDay | |
0.00% |
0 / 1 |
|
0.00% |
0 / 11 |
2862.00 | |
0.00% |
0 / 88 |
| __construct | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 6 |
|||
| is_workable | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
| is_holiday | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 5 |
|||
| get_markedDay | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 5 |
|||
| get_AllMarkedDays | |
0.00% |
0 / 1 |
30.00 | |
0.00% |
0 / 8 |
|||
| get_AllHolidays | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 5 |
|||
| get_weekDaySchedule | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| get_holidaysTemplate | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| calcuateForYear | |
0.00% |
0 / 1 |
72.00 | |
0.00% |
0 / 29 |
|||
| get_easter_datetime | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 3 |
|||
| validateWorkHoursByWeekDay | |
0.00% |
0 / 1 |
552.00 | |
0.00% |
0 / 22 |
|||
| <?php | |
| namespace ia\Work\WorkDay; | |
| class WorkDay { | |
| /* | |
| 1 ene | |
| primer lunes feb (5 feb) strtotime("first monday of $iYear", $timestamp)) | |
| tercer linues marzo (21 mar) strtotime("third monday of $iYear", $timestamp)) | |
| jue/vie santo | |
| 1 mayo | |
| 16 sept | |
| tercer lunes noviembre, (20 nov) strtotime("third monday of $iYear", $timestamp)) | |
| 25 dic | |
| 1º de diciembre de cada seis años (checar) | |
| Bancario 12 dic | |
| */ | |
| public static $defaultHolidays = [ | |
| ['title'=>'Año Nuevo', 'is_holiday'=>'Si', 'day'=>1, 'month'=>1, 'type'=>'MonthDay'], | |
| ['title'=>'Aniversario de la Constitución', 'is_holiday'=>'Si', 'day'=>5, 'month'=>2, 'type'=>'first monday'], | |
| ['title'=>'Aniversario de Benito Juárez', 'is_holiday'=>'Si', 'day'=>21, 'month'=>3, 'type'=>'third monday'], | |
| ['title'=>'Viernes Santo', 'is_holiday'=>'Si', 'day'=>31, 'month'=>3, 'type'=>'holy week', 'inc'=>-2], | |
| ['title'=>'Jueves Santo', 'is_holiday'=>'Si', 'day'=>31, 'month'=>3, 'type'=>'holy week', 'inc'=>-3], | |
| ['title'=>'Día del trabajo', 'is_holiday'=>'Si', 'day'=>1, 'month'=>5, 'type'=>'MonthDay'], | |
| ['title'=>'Día de la Independencia', 'is_holiday'=>'Si', 'day'=>16, 'month'=>9, 'type'=>'MonthDay'], | |
| ['title'=>'Día de la Revolución', 'is_holiday'=>'Si', 'day'=>20, 'month'=>11, 'type'=>'third monday'], | |
| ['title'=>'Día del la Virgen de Guadalupe', 'is_holiday'=>'Si', 'day'=>12, 'month'=>12, 'type'=>'MonthDay'], // bancario | |
| ['title'=>'Navidad', 'is_holiday'=>'Si', 'day'=>25, 'month'=>12, 'type'=>'MonthDay'], | |
| ]; | |
| //[ [ 'is_holiday'=>'Si', 'day'=>28, 'month'=>'3', 'type'=>'fixed|rule' ... ] ] | |
| private $holidaysTemplate = []; | |
| // ['y-m-d']=>[ 'is_holiday'=>'Si', ... ] | |
| private $markedDays = []; | |
| // [$year] => [ 'ymd'=>[dayInfo] ] | |
| private $yearsCalculated = []; | |
| private $monthForStrToTime = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; | |
| //@array is [1=> [[9,14],[15,18]], 2=> [[9,17]], 3=> [[9,17]], 4=> [[9,17]], 5=> [[9,17]] ] | |
| private $weekDaySchedule; | |
| /** | |
| * WorkDay::__construct() | |
| * | |
| * @param array $holidaysTemplate | |
| * @param array $weekDaySchedules | |
| * @return | |
| */ | |
| public function __construct($holidaysTemplate = null, $weekDaySchedules = null) { | |
| $this->holidaysTemplate = $holidaysTemplate === null ? self::$defaultHolidays : $holidaysTemplate; | |
| $this->weekDaySchedule = self::validateWorkHoursByWeekDay( | |
| $weekDaySchedules === null ? | |
| [1=> [[9,17]], 2=> [[9,17]], 3=> [[9,17]], 4=> [[9,17]], 5=> [[9,17]] ] : | |
| self::validateWorkHoursByWeekDay($weekDaySchedules) | |
| ); | |
| } | |
| /** | |
| * Is it a workday | |
| * | |
| * @param string|int|DateTimeInterface $anyDate | |
| * @return bool | |
| */ | |
| public function is_workable($anyDate) { | |
| if(!array_key_exists(self::dayOfWeek($anyDate), $this->weekDaySchedule )) { | |
| return false; | |
| } | |
| return !$this->is_holiday($anyDate); | |
| } | |
| /** | |
| * is it a holiday | |
| * | |
| * @param string|int|DateTimeInterface $anyDate | |
| * @return bool | |
| */ | |
| public function is_holiday($anyDate) { | |
| $ymd = self::toYmd($anyDate); | |
| $year = substr($ymd, 0, 4); | |
| if(!array_key_exists($year, $this->yearsCalculated)) { | |
| $this->calcuateForYear($year); | |
| } | |
| return array_key_exists($ymd, $this->markedDays) && $this->markedDays[$ymd]['is_holiday'] === 'Si'; | |
| } | |
| /** | |
| * Return info for a special day | |
| * | |
| * @param string|int|DateTimeInterface $anyDate | |
| * @return null|array | |
| */ | |
| public function get_markedDay($anyDate) { | |
| $ymd = self::toYmd($anyDate); | |
| $year = substr($ymd, 0, 4); | |
| if(!array_key_exists($year, $this->yearsCalculated)) { | |
| $this->calcuateForYear($year); | |
| } | |
| return array_key_exists($ymd, $this->markedDays) ? $this->markedDays[$ymd] : null; | |
| } | |
| /** | |
| * espacial dates marked and holiday | |
| * | |
| * @param int|null $year | |
| * @return array with espacial dates marked and holiday | |
| */ | |
| public function get_AllMarkedDays($year = null) { | |
| if(empty($year)) { | |
| $year = Date('Y'); | |
| if(empty($this->yearsCalculated) || !array_key_exists($year, $this->yearsCalculated)) { | |
| $this->calcuateForYear($year); | |
| } | |
| return $this->markedDays; | |
| } | |
| if(!array_key_exists($year, $this->yearsCalculated)) { | |
| $this->calcuateForYear($year); | |
| } | |
| return $this->yearsCalculated[$year]; | |
| } | |
| /** | |
| * Holidays | |
| * | |
| * @param int|null $year | |
| * @return array | |
| */ | |
| public function get_AllHolidays($year = null) { | |
| $holidays = []; | |
| foreach($this->get_AllMarkedDays($year) as $ymd => $dayInfo) { | |
| if($dayInfo['is_holiday'] === 'Si') { | |
| $holidays[$ymd] = $dayInfo; | |
| } | |
| } | |
| return $holidays; | |
| } | |
| /** | |
| * WorkDay::get_weekDaySchedule() | |
| * | |
| * @return array | |
| */ | |
| public function get_weekDaySchedule() { | |
| return $this->weekDaySchedule; | |
| } | |
| /** | |
| * WorkDay::get_holidaysTemplate() | |
| * | |
| * @return array | |
| */ | |
| public function get_holidaysTemplate() { | |
| return $this->holidaysTemplate; | |
| } | |
| // ______________________________________________________________________________________________________________ | |
| /* | |
| // _______________ | |
| //public function set_holidaysTemplate(array $holidaysTemplate) { | |
| $this->holidaysTemplate = $holidaysTemplate; | |
| $this->markedDays = []; | |
| $this->yearsCalculated = []; | |
| } | |
| // Template ie al inicio poner el template para todos? _________________________________________ | |
| //public static function get_holidaysTemplateDefault() { | |
| return self::$holidaysTemplateDefault; | |
| } | |
| //public static function set_holidaysTemplateDefault(array $holidaysTemplateDefault) { | |
| self::$holidaysTemplateDefault = $holidaysTemplateDefault; | |
| } | |
| */ | |
| // ________________________________________________________________________________________________________________________ | |
| /** | |
| * WorkDay::calcuateForYear() | |
| * | |
| * @param int $year | |
| * @return void | |
| */ | |
| private function calcuateForYear($year) { | |
| foreach($this->holidaysTemplate as $dayInfo) { | |
| $ymd = "$year-".str_pad($dayInfo['month'],2,'0',STR_PAD_LEFT)."-".str_pad($dayInfo['day'],2,'0',STR_PAD_LEFT); | |
| switch($dayInfo['type']) { | |
| case 'MonthDay': | |
| $dayInfo['realday'] = $dayInfo['holiday'] = $ymd; | |
| $this->yearsCalculated[$year][$ymd] = $this->markedDays[$ymd] = $dayInfo; | |
| break; | |
| case 'ExactDate': | |
| if($dayInfo['year'] == $year) { | |
| $ymd = "$dayInfo[year]-".str_pad($dayInfo['month'],2,'0',STR_PAD_LEFT)."-".str_pad($dayInfo['day'],2,'0',STR_PAD_LEFT); | |
| $dayInfo['realday'] = $dayInfo['holiday'] = $ymd; | |
| $this->yearsCalculated[$year][$ymd] = $this->markedDays[$ymd] = $dayInfo; | |
| } | |
| break; | |
| case 'holy week': | |
| $easterHoliday = $this->get_easter_datetime($year, empty($dayInfo['inc']) ? 0 : (int)$dayInfo['inc'] ); | |
| $ymd = $easterHoliday->format('Y-m-d'); | |
| $this->markedDays[$ymd] = $dayInfo; | |
| $dayInfo['realday'] = $dayInfo['holiday'] = $ymd; | |
| $this->yearsCalculated[substr($ymd,0,4)][$ymd] = $dayInfo; | |
| break; | |
| default: | |
| $dayInfo['realday'] = $ymd; | |
| $ymdHoliday = Date('Y-m-d', strtotime("$dayInfo[type] of ".$this->monthForStrToTime[$dayInfo['month']]." $year") ); | |
| $dayInfo['holiday'] = $ymdHoliday; | |
| $this->markedDays[$ymdHoliday] = $dayInfo; | |
| $this->yearsCalculated[substr($ymdHoliday,0,4)][$ymdHoliday] = $dayInfo; | |
| if($dayInfo['realday']!==$dayInfo['holiday']) { | |
| $dayInfo['is_holiday'] = 'No'; | |
| $this->yearsCalculated[substr($ymd,0,4)][$ymd] = $this->markedDays[$ymd] = $dayInfo; | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * WorkDay::get_easter_datetime() | |
| * | |
| * @param int $year | |
| * @param int $incDays | |
| * @return DateTime | |
| */ | |
| private function get_easter_datetime($year, $incDays = 0) { | |
| $base = new DateTime("$year-03-21"); | |
| $days = easter_days($year) + $incDays; | |
| return $base->add(new DateInterval("P{$days}D")); | |
| } | |
| // __ WEEKENDS _______________________________________________________________ | |
| /** | |
| * Checks if workHoursByWeekDay is valid. | |
| * | |
| * @param array $workHoursByWeekDay | |
| * @throws Exception | |
| * @return array | |
| */ | |
| public static function validateWorkHoursByWeekDay(array $workHoursByWeekDay) { | |
| if(empty($workHoursByWeekDay) || !is_array($workHoursByWeekDay)) { | |
| throw new Exception("Invalid workHoursByWeekDay Expected [ 1=>[[8,14],[15,17], ]"); | |
| } | |
| foreach($workHoursByWeekDay as $dayOfWeek => &$horarios) { | |
| if($dayOfWeek < 0 || $dayOfWeek > 6) { | |
| throw new Exception("Invalid day of week '$dayOfWeek' must be 0-6"); | |
| } | |
| if(empty($horarios) || !is_array($horarios)) { | |
| throw new Exception("Day of week '$dayOfWeek' has invalid horarios must be '$dayOfWeek'=>[[8,14],[15,17],]"); | |
| } | |
| foreach($horarios as &$rango1) { | |
| if($rango1[0]>$rango1[1]) { | |
| $swap = $rango1[0]; | |
| $rango1[0] = $rango1[1]; | |
| $rango1[1] = $swap; | |
| } | |
| } | |
| unset($rango1); | |
| uasort($horarios, function($a, $b) { return $a[0]<=>$b[0]; }); | |
| $prev = [-1,-1]; | |
| foreach($horarios as $rango) { | |
| if(empty($rango) || !is_array($rango) || count($rango) !== 2 || | |
| $rango[0]<0 || $rango[0]>23 || $rango[1]<0 || $rango[1]>24 || $rango[0]>=$rango[1] | |
| ){ | |
| throw new Exception("Day of week '$dayOfWeek' has invalid hour range ".print_r($rango, true)); | |
| } | |
| if($rango[0] < $prev[0] || $rango[0] < $prev[1] || $rango[1] < $prev[0] || $rango[1] < $prev[1] ) { | |
| throw new Exception("Day of week '$dayOfWeek' hour range ".print_r($rango, true)." conflicts with previous entry: ".print_r($prev, true)); | |
| } | |
| $prev = $rango; | |
| } | |
| } | |
| return $workHoursByWeekDay; | |
| } | |
| } |