Classe feuille de temps php5

Contenu du snippet

Voici une classe PHP5 pour la gestion de feuille de temps en vue d'effectuer par exemple une estimation de date de fin en jours ouvrés.

Calcul exact des jours ouvrés grâce à 1 Calcul des jours fériés.

Calcul de la date et heure de fin à partir d'une durée de charge en j/h avec nombre à virgules flottantes (optimisation réélle à 1 chiffre après la virgule en paramétrant l'interval minimale [iMinIntervalPeriod] à une valeur > 0.1 ).

Possibilité de paramétrer les jours de repos par défaut samedi dimanche.

Methode de calcul par paramétrage du plus petit interval en j/h par défaut 0.01
La valeur 0.01 ne convient pour des performances optimales => valeur choisie uniquement pour exemple.
[addInterval]

Derniière MAJ Modification de l'init:
Ajout de contrôles pour ne pas saisir n'importe quoi.
Optimisations ajout de methodes privées
En attendant de trouver une autre méthode qui n'utilise pas l'ajout successif d'intervalles pour le calcul

Source / Exemple :


<?php
class WorkingTimeSheet
{
  /**
  @property :int
  @desc :temps écoulé depuis le début de la journée en s

  • /
private $iElapsedTime; /** @property :int @desc : timestamp en cours
  • /
private $iCurrentTimestamp; /** @property :array @desc :Les jours fériés de l'année en cours
  • /
private $aBankHolydays; /** @property :double @desc :Dernière Periode ajoutée
  • /
private $dPeriod; /** @property :array @desc : les jours de la semaine en francophone
  • /
public static $aWDays=array(0=>'Dimanche', 1=>'Lundi', 2=>'Mardi', 3=>'Mercredi', 4=>'Jeudi', 5=>'Vendredi', 6=>'Samedi'); /** @property :array @desc : Les options de configuration à passer dans le constructeur ou à configurer par la methode configureProperties iStartingTimestamp: Timestamp pour la date heure de début définissant également l' Horaire d'ouverture quotidienne. iTimePerDay: duree d'une journée travaillée en seconde sFormat: Format de date pour affichage iEffectiveStartTimestamp : prend en compte l'heure de début effective du calcul dans le cas ou une tache ne commencerait pas au moment de l'ouverture quotidienne inclus dans iStartingTimestamp. bClosedOnClosedDays : Booléen à true si les jours fermés ne sont pas travaillés => true par défaut false sinon aWeeklyClosedDays : Les jours chomés de la semaine Defaut Samedi 6 Dimanche 0
  • /
protected $aOptions=array( 'iStartingTimestamp'=>0, 'iEffectiveStartingTimestamp'=>NULL, 'iTimePerDay'=>28800, 'sFormat'=>'d/m/Y H:i:s', 'bClosedOnClosedDays'=>true, 'aWeeklyClosedDays'=>array(6,0), 'dMinIntervalPeriod'=>0.01); /** @param :mixed @desc : $prop est la propriété à récupérer possible uniquement à l'interieur de la classe
  • /
protected function __get($prop) { if (property_exists(get_class($this),$prop)) return $this->$prop; if (!array_key_exists($prop,$this->aOptions)) throw new Exception(__CLASS__.'::'.__FUNCTION__. ' clé option inexistante '.$prop); return $this->aOptions[$prop]; } /** @param :mixed $prop @param :mixed $value @desc : $prop est la propriété à définir possible uniquement à l'interieur de la classe
  • /
protected function __set($prop,$value) { if (property_exists(get_class($this),$prop)) $this->$prop=$value; if (!array_key_exists($prop,$this->aOptions)) throw new Exception(__CLASS__.'::'.__FUNCTION__. ' clé option inexistante '.$prop); $this->aOptions[$prop]=$value; } /** @param :array $aProps @desc : Configuration des options Possibilité de passer un tableau incomplet à condition que chaque clé existe Les valeurs du tableau non renseignées sont celles configurés par défaut en définition
  • /
public function configureProperties($aProps) { if (!is_array($aProps)) throw new Exception(__CLASS__.'::'.__FUNCTION__. ' paramettre invalide '); foreach($aProps as $key=>$val) { if (!array_key_exists($key,$this->aOptions)) { throw new Exception(__CLASS__.'::'.__FUNCTION__. ' clé option inexistante '.$key); } $this->aOptions[$key]=$val; } } /** @desc : Validation et Initialisation des Propriétés privées ou des propriétés non définies.
  • /
private function validProperties() { //echo '<br/>avant validProp'.(date('H',$this->iEffectiveStartingTimestamp)); if (!is_int($this->iStartingTimestamp)) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type int attendu L '.__LINE__); if (!is_int($this->iEffectiveStartingTimestamp)&& $this->iEffectiveStartingTimestamp!==NULL) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type int attendu L '.__LINE__); if (!is_int($this->iTimePerDay)) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type int attendu L '.__LINE__); if (!is_string($this->sFormat)) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type string attendu L '.__LINE__); if (!is_bool($this->bClosedOnClosedDays)) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type bool attendu L '.__LINE__); if (!is_double($this->dMinIntervalPeriod)) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : Type double attendu L '.__LINE__); if ($this->dMinIntervalPeriod==0) throw new Exception (__CLASS__.' :: '.__FUNCTION__. ' : 0 interdit '.__LINE__); if ($this->isClosed($this->iCurrentTimestamp)) $this->nextOpenedTimestamp(); if ($this->iEffectiveStartingTimestamp===NULL) $this->iEffectiveStartingTimestamp=$this->iCurrentTimestamp; else $this->iEffectiveStartingTimestamp=mktime( date('H',$this->iEffectiveStartingTimestamp), date('i',$this->iEffectiveStartingTimestamp), date('s',$this->iEffectiveStartingTimestamp), date('m',$this->iCurrentTimestamp), date('d',$this->iCurrentTimestamp), date('Y',$this->iCurrentTimestamp)); //echo '<br/>après validProp'.(date('H',$this->iEffectiveStartingTimestamp)); $this->iElapsedTime=$this->iEffectiveStartingTimestamp-$this->iCurrentTimestamp; $this->iCurrentTimestamp=$this->iEffectiveStartingTimestamp; } /** @param :mixed $mProps optionnel par défaut le timestamp actuel est récupéré @desc : Constructeur Configuration des options
  • /
public function __construct($mProps=NULL) { if ($mProps===NULL) $this->iStartingTimestamp=mktime(); if (is_array($mProps)) { $this->configureProperties($mProps); } else if (is_int($mProps)) $this->iStartingTimestamp=$mProps; $this->iCurrentTimestamp=$this->iStartingTimestamp; $this->buildBankHolidays(); $this->validProperties(); } /** @desc : Affiichage
  • /
public function __toString() { return '<br/>DEBUT SAISI : '. self::$aWDays[date('w',$this->iStartingTimestamp)]. ' '.date($this->sFormat,$this->iStartingTimestamp). '<br/>DEBUT EFFECTIF : '. self::$aWDays[date('w',$this->iEffectiveStartingTimestamp)]. ' '.date($this->sFormat,$this->iEffectiveStartingTimestamp). '<br/>FIN : '. self::$aWDays[date('w',$this->iCurrentTimestamp)]. ' '.date($this->sFormat,$this->iCurrentTimestamp). '<br/>Durée Ecoulée en jour ouvrés: '.$this->dPeriod.'<br/>'; } /** @param int @return int @desc : Donne le temps écoulé depuis la date de début de la WorkTimeSheet Ne pas utiliser
  • /
private function getElapsedTimestampFrom($Timestamp) { return ($Timestamp-$this->iStartingTimestamp); } /** @param int optionnel @desc : Construit le tableau de jours feries
  • /
private function buildBankHolidays($ts=NULL) { if ($ts===NULL) $year=date('Y',$this->iStartingTimestamp); else $year=date('Y',$ts); $this->aBankHolydays=array('Jour de l\'an'=>mktime(0,0,0,1,1,$year), 'Fete du Travail'=>mktime(0,0,0,5,1,$year), 'Armist. 1945'=>mktime(0,0,0,5,8,$year), 'Fete nat'=>mktime(0,0,0,7,14,$year), 'Assomption'=>mktime(0,0,0,8,15,$year), 'Toussaint'=>mktime(0,0,0,11,1,$year), 'Armist. 1918'=>mktime(0,0,0,11,11,$year), 'Noel'=>mktime(0,0,0,12,25,$year)); //pâques $G=$year%19; $C=floor($year/100); $C_4=floor($C/4); $E=floor((8*$C+13)/25); $H=(19*$G+$C-$C_4-$E+15)%30; $K=floor($H/28); $P=floor(29/($H+1)); $Q=floor((21-$G)/11); $I=($K*$P*$Q -1)*$K+$H; $B=floor($year/4)+$year; $J1=$B+$I+2+$C_4-$C; $J2=$J1%7; $R=28+$I-$J2; $day=(int)date('d',(mktime(0,0,0,3,1+$R,$year))); $mth=(int)date('m',(mktime(0,0,0,3,1+$R,$year))); $this->aBankHolydays['Lundi de paques']=mktime(0,0,0,$mth,$day,$year); //ascension $dasc=(int)date('d',(mktime(0,0,0,$mth,$day+38,$year))); $masc=(int)date('m',(mktime(0,0,0,$mth,$day+38,$year))); $this->aBankHolydays['ascension']=mktime(0,0,0,$masc,$dasc,$year); //pentecôte $dasc=(int)date('d',(mktime(0,0,0,$mth,$day+49,$year))); $masc=(int)date('m',(mktime(0,0,0,$mth,$day+49,$year))); $this->aBankHolydays['Lundi de Pentecote']=mktime(0,0,0, $masc,$dasc,$year); } /** @param int @return bool @desc : Indique si un timestamp est un jour fermé
  • /
public function isClosed($ts) { $wdts=(int)date('w',$ts); $ts=mktime(0,0,0,date('m',$ts),date('d',$ts),date('Y',$ts)); $isBankH=in_array($ts,$this->aBankHolydays); $isWklyClosed=in_array($wdts,$this->aWeeklyClosedDays); if(!$isBankH) if ($isWklyClosed && $this->bClosedOnClosedDays===true) return true; if ($this->bClosedOnClosedDays===false && ($isBankH||$isWklyClosed)) return false; if ($isBankH) return true; if (!$isWklyClosed) return false; return true; } /** @param int @desc : Définit l'heure de début d'une tache dans la même journée que la propriété iStartingTimestamp si une autre date est incluse elle n'est pas prise en compte seule l'heure importe.
  • /
public function beginWorkSheetAt($timestamp) { $this->iEffectiveStartingTimestamp=$timestamp; $this->validProperties(); } /** @desc : Positionne le timestamp courant sur la prochaine date d'ouverture sans considérer la date courante
  • /
private function nextOpenedTimestamp() { do { $lastYear = date('Y',$this->iCurrentTimestamp); $this->iCurrentTimestamp=mktime(date('H',$this->iStartingTimestamp), date('i',$this->iStartingTimestamp), date('s',$this->iStartingTimestamp), date('m',$this->iCurrentTimestamp), date('d',$this->iCurrentTimestamp)+1, date('Y',$this->iCurrentTimestamp)); if (date('Y',$this->iCurrentTimestamp) !=$lastYear) $this->buildBankHolidays($this->iCurrentTimestamp); } while ($this->isClosed($this->iCurrentTimestamp)); } /** @desc : Ajoute le plus petit interval de temps possible au timestamp courant
  • /
private function addInterval() { if ($this->iElapsedTime >= $this->iTimePerDay ) { $this->iElapsedTime=0; $this->nextOpenedTimestamp(); } $this->iElapsedTime+=(int)($this->iTimePerDay*$this->dMinIntervalPeriod); $this->iCurrentTimestamp+=(int)($this->iTimePerDay*$this->dMinIntervalPeriod); } /** @param double $days @desc : Ajout du nombre de jours ouvrés en décimal au timestamp courant procède par ajout d'intervalles
  • /
public function addFloatingDays($dDays) { $this->dPeriod=$dDays; $nbOfIntervals=$dDays/$this->dMinIntervalPeriod; while ($nbOfIntervals>0) { $this->addInterval(); $nbOfIntervals--; } } /** @desc : retourne les jours feries
  • /
public function getBankHolydays() { return $this->aBankHolydays; } /** @desc : retourne les jours de repos de la semaine
  • /
public function getWeeklyClosedDays() { return $this->aWeeklyClosedDays; } /** @return int @desc : retourne le timestamp courant
  • /
public function getTimestamp() { return $this->iCurrentTimestamp; } } try { // Exemple de feuille de temps commençant tous les jours à 10:00:00: // l'heure de cette date passée en paramètre est gardée comme // heure d'ouverture quotidienne. // On peut commencer le calcul d'une durée ultérieurement dans cette // journée de debut en passant par la methode beginWorkSheetAt($timestamp) // ou par la clé iEffectiveStartingTimestamp du tableau d'options en parametre $Options=array('iStartingTimestamp'=>mktime(10,0,0,12,25,2007), 'iEffectiveStartingTimestamp'=>mktime(14,0,0), 'iTimePerDay'=>28800, 'sFormat'=>'d/m/Y H:i:s', 'bClosedOnClosedDays'=>true, 'aWeeklyClosedDays'=>array(6,0), 'dMinIntervalPeriod'=>0.1); $WorkTime=new WorkingTimeSheet($Options); // Ex Si La premiere feuille commence à 14 heure le premier jour // configuration possible par le constructeur ou par // configureProperties() //$WorkTime->beginWorkSheetAt(mktime(14,0,0)); // calcul la date de fin $WorkTime->addFloatingDays(5.5); // récuperation des jours fériés $Feries = $WorkTime->getBankHolydays(); $Fermes= $WorkTime->getWeeklyClosedDays(); // récupération du timestamp de fin si besoin. $endTimestamp=$WorkTime->getTimestamp(); // écriture de la date de fin par appel implicite à __toString() echo $WorkTime; foreach ($Feries as $key=> $val) { echo '<br/>'.$key.' : '.WorkingTimeSheet::$aWDays[date('w',$val)]. ' '.date('d/m/Y',$val); } foreach ($Fermes as $val) { echo '<br/> : '.WorkingTimeSheet::$aWDays[$val]; } } catch (Exception $e) { echo $e->getMessage(); } ?>

Conclusion :


Voilà N'hésitez pas à me faire part de possibles bugs

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.