IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Fonction de calcul en fonction de dates.


Sujet :

Langage PHP

  1. #1
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut Fonction de calcul en fonction de dates.
    Bonjour à tous

    Voilà je viens vers vous avez un petit souci, sur lequel je travaille depuis un bon bout de temps mais sans succès :/ !

    Pour mon entreprise, j'essaie de faire une fonction qui calculerais les tarifs des astreintes des salariés. Je vous explique vite fait le "cahier des charges" avant de vous montrer mon code et donner le point où je bloque. Je sais que ce qui me bloque le plus c'est un manque de connaissances des manipulations des dates en PHP (malgré le suivi de plusieurs tuto) ...

    Alors voilà

    - Le salarié rentre un date de début d'astreinte (un datetime), et la durée (en minute) de cette astreinte.
    - le tarif horaire est de 70 euros la 1ière heure, 35 euros la 2ième, 35 euros la 3ième, 35 euros la 4ième, puis après c'est par tranche de 2h à 70 euro.
    - Ceci sont les tarifs du lundi au vendredi, le samedi ils sont majorés de 20%, et le dimanche de 50% (important : si 1h est à cheval sur 2 jours à tarifs différents, on calcul par minute. par exemple de 23h40 à 00h40, entre vendredi est samedi, les 20 1ière minutes sont facturés à 35e/h, et les 40 suivantes à (35e/h)*1.2)
    - du lundi au vendredi les horaires d'astreintes sont de 20h à 7h30, le samedi et le dimanche tout le jours entier. Donc une astreinte qui démarre à 19h un mardi et dure 3h ne sera facturé que 2h puisque le tarif d'astreinte commence à 20h.
    - important : toute heure entamée est payée en entière (de même pour les tranches de 2h, donc une intervention de 4h20min sera facturé 6h puis la tranche de 2h est entamé.


    voilà mon code :

    (je n'arrive pas à gérer :
    - le cas où, en semaine, l'opération commence avant 7h30 et fini après 20h. Par exemple une astreinte de 6h30 à 21h d'un durée donc de 870 minutes un lundi, sera facturé 70 euro (la 1ière heure de 6h30 à 7h30) + 35 euro (de 20h à 21h) soit 105 euros
    - le cas du chevauchement entre vendredi/samedi, samedi/dimanche et dimanche/lundi pour le passage en tranche de 2h après la 4ième heure
    )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    function calculTarif($datedebut, $duree){
    	list($date, $time) = explode(' ', $datedebut);
    	list($year, $month, $day) = explode('-', $date);
    	list($hour, $minute, $second) = explode(':', $time);
    	$matin = "07:30:00";
    	$soir = "20:00:00";
    	$timestampStart = mktime($hour, $minute, $second, $month, $day, $year);
    	$startDay = date("N", $timestampStart);
    	$timestampEnd = $timestampStart + ($duree*60);
    	$endDay = date("N", $timestampEnd);
    	$finheureshno = date("d-M-Y H:m:i", $timestampEnd);
    	list($date1, $time1) = explode(' ', $finheureshno);
    	$minuit = mktime(0, 0, 0, $month, $day, $year) + 86400 ;
    	if ((strtotime($matin) < strtotime($time)) && (strtotime($time) < strtotime($soir)) && (($startDay == 1) || ($startDay == 2) || ($startDay == 3) || ($startDay == 4) || ($startDay == 5))){
    		$debutpaye = mktime(20, 0, 0, $month, $day, $year);
    		$heureho = (strtotime($soir) - strtotime($time)) / 60;
    		$heureshno = $duree - $heureho;
    	}else{
    		$debutpaye = $timestampStart;
    		$heureshno = $duree;
    	}
    	if ((strtotime($matin) < strtotime($time1)) && (strtotime($time1) < strtotime($soir)) && (($startDay == 1) || ($startDay == 2) || ($startDay == 3) || ($startDay == 4) || ($startDay == 5))){
    		$finpaye = mktime(7, 30, 0, $month, $day, $year);
    		$heureho1 = (strtotime($time1) - strtotime($matin)) / 60;
    		$heureshno = $duree - $heureho1;
    	}else{
    		$finpaye = $timestampEnd;
    		$heureshno = $duree;
    	}
    	$diffDay1 = $minuit - $debutpaye;
    	$diffDay2 = $finpaye - $minuit;
    	$heuresDay1 = floor($diffDay1/3600);
    	$resteDay1 = ($diffDay1 % 3600)/60;
    	$heuresDay2 = floor($diffDay2/3600);					
    	$resteDay2 = ($diffDay2 % 3600)/60;
    	$addition = $resteDay1 + $resteDay2;
    	if ($addition == 0){
    		$heureEntame = $addition;
    	}elseif (($addition < 60) && ($addition > 0) ){
    		$heureEntame = 60 - $addition;
    	}else{
    		$heureEntame = 120 - $addition;
    	}
    	$totalHeures = $heuresDay1 + $heuresDay2;
    	$prixPremiereHeure = 70;
    	$prixHeure = 35;
    	$prisheureDouble = 70;
    	$prixMinutePremiereHeure = 70/60;
    	$prixMinuteHeure = 35/60;
    	$prixMinuteHeureDouble = 70/60;
    	if (($heureshno%60)==0) {
    		$heuresComptees = ($heureshno/60);
    	}else{
    		$heuresComptees = ceil($heureshno/60);
    	}
    	if($heuresComptees > 4){
        		$tarif = $prixPremiereHeure + (3 * $prixHeure) + (ceil(($heuresComptees - 4)/2) * $prisheureDouble);
           	}
           	else{
           		$tarif = $prixPremiereHeure + (($heuresComptees - 1) * $prixHeure);
           	}
           	$tarifDay1 = ($prixHeure + ($heuresDay1 * $prixHeure) + ($resteDay1 * $prixMinuteHeure));
           	$tarifDay2 = (($heuresDay2 * $prixHeure) + ($resteDay2 * $prixMinuteHeure) + ($heureEntame * $prixMinuteHeure));
          	if ($startDay==$endDay){ //Pour OP dans la même journée
    	        switch ($startDay) {
    	    		case 1:
    	    		case 2:
    	    		case 3:
    	        	case 4:
    	    		case 5:
    	       			$tarifOP = $tarif;
    	        		break;
    	    		case 6:
    	    			$tarifOP = $tarif * 1.2;
    	        		break;
    	        	case 7:
    	        		$tarifOP = $tarif * 1.5;
    	        		break;
    		}
    	}else{ //Pour OP à cheval sur 2 jours 
    		if(($startDay == 1) || ($startDay == 2) || ($startDay == 3) || ($startDay == 4)){
    			$tarifOP = $tarif;
    		}elseif(($startDay == 5) && ($endDay == 6)){
    			$tarifOP = $tarifDay1 + ($tarifDay2 * 1.2);
    		}elseif(($startDay == 6) && ($endDay == 7)){
    			$tarifOP = ($tarifDay1 * 1.2) + ($tarifDay2 * 1.5);
    		}elseif(($startDay == 7) && ($endDay == 1)){
    			$tarifOP = ($tarifDay1 * 1.5) + $tarifDay2;
    		}
    	}
    	return ceil($tarifOP);
    }
    désolé pour le nom des variables c'est un peu brouillon mais ça doit faire 1 semaine que je suis sur ça et à force d'essais et d'essais ça me désespère et j'en oublis d'être propre ...

    En espérant que vous pourrez me donner de sérieuses pistes d'aide

    Cordialement,

    Paul.

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    En traitant des cas complexes comme ça, sans mettre aucun commentaire dans ton code, tu vas dans le mur c'est sûr.
    Il serait également très intéressant d'écrire des fonctions pour les actions élémentaires.
    Par exemple une fonction qui à partir de deux dates, fourni la zone de facturation à appliquer et une fonction qui gère la facturation.
    Cela permet, une fois ces fonctions écrites et fonctionnelles de se reposer entièrement dessus.

    Moi j'aurais plutôt vu un principe d'horloge.
    C'est à dire en partant de l'horaire de départ, avancer dans le temps.

    Je t'ai écris sur le pouce et sans être bien sûr d'avoir compris tous les détails de facturation un petit exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <?php
    define('FACTURATION_NA', 0);
    define('FACTURATION_SEMAINE', 1);
    define('FACTURATION_WE', 2);
     
    // fonction qui donne la période de facturation
    function plage_facturation($objDate) {
    	$heure = $objDate->format('hi');
    	$joursem = $objDate->format('N');
            // lundi - vendredi
    	if ($joursem < 6) {
    		if ($heure <= 730 || $heure >= 2000) {
    			return FACTURATION_SEMAINE;	
    		}
    	}
            // week-end
    	else {
    		return FACTURATION_WE;
    	}
    	return FACTURATION_NA;
    }
     
    // traitement
    $objDate = date_create('2014-02-21 19:48');
    $duree = 364;
    $facturation = array(FACTURATION_NA=>0, FACTURATION_SEMAINE=>0, FACTURATION_WE=>0);
     
    for ($i = 0; $i < $duree; $i++) {
    	$plage_facturation = plage_facturation($objDate);
    	if (plage_facturation($objDate) !== FALSE) {
    		$facturation[$plage_facturation]++;
    	}
    	$objDate->modify('+1 minute');
    }
     
    // résultat 
    print_r($facturation);
    // Array ( [0] => 12 [1] => 240 [2] => 112 ) 
    // 12 minutes non facturées
    // 240 minutes en semaine
    // 112 minutes en we
    J'avance minute par minute, ce n'est peut être pas le plus efficace dans ton cas mais c'est simple à écrire, à lire et à debuguer.
    L'idée était de te montrer comment aborder la chose plus simplement.
    Par exemple avec l'écriture d'une fonction, je dégage un gros bloc de code de ma partie de traitement ; mon code devient plus clair : je sais que si j'ai un problème de repartition de mes minutes, cela que ma fonction ne fournit pas le bon résultat ou que je ne lui donne pas la bonne donnée.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut
    Merci beaucoup d'avoir pris le temps de m'aider !

    Et merci pour tes conseils ... C'est vrai que séparer en plusieurs fonction ça serait plus simple pour voir d'où viennent les problème. Et commenter aussi (même si j'avais un prof qui nous disait "avec des variables et des fonctions correctement nommés, il y a pas besoin de commentaire")

    Et ton idée d'avancer minute par minute est tout simplement géniale ! ça résout mon souci de chevauchement sur plusieurs jours et des heures non payés ! Ça parait tout bête mais ça m'avait même pas effleuré l'esprit ...

    Et tu viens de m'apprendre "$heure = $objDate->format('Hi');" alors que moi je m'étais 15 ligne de explode pour récupérer l'heure de la date ...

    Je vais travailler dessus et poster une fois que j'aurais fini ça pourrait toujours aider d'autre gens

    Encore merci !

  4. #4
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut
    En travaillant à partir de ton code pour avoir une piste, je me suis rendu compte d'un souci.

    Avec ton exemple '2014-02-21 19:48' ça fonctionne, mais sur d'autre cas ça ne marche pas ...

    Par exemple si je met '2014-02-21 07:00', normalement je devrais avoir au print_r($facturation) :

    Array ( [0] => 30 [1] => 30 [2] => 0 [3] => 0 ) puisque la limite est à 7h30.

    Or il m'affiche :

    Array ( [0] => 60 [1] => 0 [2] => 0 [3] => 0 ) ... Donc entièrement en non payé alors que de 7h à 7h30 on est censé être payé.

    Si on démarre avec une heure située dans l'intervalle non payé, et qu'on en sort,ça fonctionne, mais si on démarre en dehors de l'intervalle non payé en y rentrant ça ne fonctionne plus ça met directement les heures en non payés ...

    Ton code est extrêmement clair et bien détaillé mais je ne vois pas d'où le problème peut venir :/ ...


    EDIT !!!

    Après plusieurs test, je me suis rendu compte que malgré :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if ($heure <= 0730 || $heure >= 2000) {
                return FACTURATION_SEMAINE; 
            }
    le changement horaire du matin se fait à 4h30 ... car si je met heure de début 4h et durée 60 minute, là ça me met bien 30/30 ...

    il y a-t-il une erreur dans le 0730 qui désigne donc 4h30 au lieu de 7h30 ? alors que 2000 désigne bien 20h ...

  5. #5
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    J'ai corrigé discrètement une erreur sur cette partie ce matin dans le message d'origine
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  6. #6
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut
    Oui j'a corrigé d'une manière différente entre-temps mais qui à l'air de fonctionner aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $heure = $objDate->format('H:i');
    if ($heure <= '07:29' || $heure >= '20:00') {
    Je dois mettre 07:29 car avec 7:30 il y a un décalage d'1 minute.

    j'ai essayé avec 'hi' et '730' ça met aussi le décalage de 1 minute et avec 729 c''est réglé Donc voilà !

    Merci encore pour ta précieuse aide ! ça fait plusieurs jours que je suis dessus et grâce à ton idée de minute c'est quasiment fini !

    Voilà le code qui fonctionne :

    (il n'y a qu'un seul cas qui n'est pas géré je l'explique en dessus si quelqu'un a une piste )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    <?php
     
    // CONSTANTES DEFINIT DANS /app/Config/bootstrap.php car j'utilise CakePHP
    //define('FACTURATION_NA', 0);
    //define('FACTURATION_SEMAINE', 1);
    //define('FACTURATION_SAMEDI', 2);
    //define('FACTURATION_DIMANCHE', 3);
     
    // fonction qui donne la période de facturation
    static function plage_facturation($objDate) {
        $heure = $objDate->format('H:i');
        $joursem = $objDate->format('N');
        print_r($heure);
        echo "</br>";
        // lundi - vendredi
        if ($joursem < 6) {
            if ($heure <= '07:29' || $heure >= '20:00') {
                return FACTURATION_SEMAINE; 
            }
        }
        // samedi
        elseif ($joursem == 6){
            return FACTURATION_SAMEDI;
        }
        // dimanche
        elseif ($joursem == 7){
            return FACTURATION_DIMANCHE;
        }
        return FACTURATION_NA;
    }
     
    // fonction qui ajoute les heures entamées
    static function heure_entammee($duree) {
        if ($duree <= 240){
            if (($duree%60) != 0){
                $duree = $duree - ($duree%60) + 60;
            }
        }
        else {
            $reste = $duree - 240;
            if (($reste%120) != 0){
                $duree = $duree - ($reste%120) + 120;
            }
        }
        return $duree;
    }
     
    // fonction qui calcul le prix
    static function tarification($facturation, $jourDepart) {
        print_r($jourDepart);
        if ($jourDepart < 6) {
            $tarification = 35 + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
            return $tarification;
        }elseif ($jourDepart == 6){
            $tarification = (35*1.2) + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
            return $tarification;
        }elseif ($jourDepart == 7){
            $tarification = (35*1.5) + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
            return $tarification;
        }
    }
     
    static function calculTarif($datedebut, $duree){
    	// traitement
    	$objDate = date_create($datedebut);
    	$jourDepart = $objDate->format('N');
    	$duree = $duree;
    	$dureePayee = Post::heure_entammee($duree);
    	$facturation = array(FACTURATION_NA=>0, FACTURATION_SEMAINE=>0, FACTURATION_SAMEDI=>0, FACTURATION_DIMANCHE=>0);
    	for ($i = 0; $i < $dureePayee; $i++) {
    	    $plage_facturation = Post::plage_facturation($objDate);
    	    if (Post::plage_facturation($objDate) !== FALSE) {
    	        $facturation[$plage_facturation]++;
    	    }
    	    $objDate->modify('+1 minute');
    	}
    	// résultat 
    	$prix = Post::tarification($facturation, $jourDepart);
    	return ceil($prix);
    }

    Donc après de nombreux test unitaire, le seul cas pas géré est le suivant (je vais essayer d'être clair ^^') :

    - Toute heure entamée est due. Donc un travail de 1h10 sera rémunéré 2h. J'ai donc fait la fonction heure_entamee qui s'occupe de ça. Elle arrondit $duree au multiple de 60 supérieur. Elle fonctionne sur des heures normales. Mais dans le cas où la fin de la durée tombe dans une période NON-PAYE, et bien cela ne fonctionne pas.

    Exemple : Sachant que la limite est à 7h30, une personne commençant à 6h pour un astreinte 1h10, devrait être payée 2h, mais n'est payée que 1h30 vu que la dernière demi-heure de l'heure entamée tombe dans les horaires non payé.

    L'erreur vient de la fonction heure_entamee ? ou c'est ailleurs que je devrais gérer ce cas ?

  7. #7
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Ton exemple contredit la règle "heure commencée - heure payée"
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  8. #8
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    J'ai revu un ancien script à moi qui calculait des temps sur des plages horaires.
    Il ressemble plus à ton script de départ : il calcule jour par jour le temps passé en regardant comment se chevauche les périodes.
    La lecture des conditions sur les 3 cas est assez obscure comme ça mais il suffit de prendre un feuille et de dessiner une ligne de temps pour comprendre comment ça marche.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?php
     
    function delai_plage($objT1, $objT2, $date, $plages) {
     
    	$temps = 0;
     
    	$dmY1 = $objT1->format('dmY');
    	$dmY2 = $objT2->format('dmY');
    	$datedmY = $date->format("dmY");
     
    	foreach ($plages as $plage) {
    		$objT3 = date_create($date->format('Y-m-d ' . $plage['debut']));
    		$objT4 = date_create($date->format('Y-m-d ' . $plage['fin']));
     
    		if ($datedmY != $dmY1 && $datedmY != $dmY2) { // jour complet
    			$temps += $objT4->format('U') - $objT3->format('U');
    		}
    		elseif ($datedmY == $dmY1 && $datedmY == $dmY2 && $objT1 < $objT4 && $objT2 > $objT3) { // sur un jour unique
    			$temps += min($objT4->format('U'), $objT2->format('U')) - max($objT3->format('U'), $objT1->format('U'));
    		}
    		elseif ($datedmY == $dmY1 && $datedmY != $dmY2 && $objT4 > $objT1) { // premier jour de la période et plage se terminant apres le début
    			$temps += $objT4->format('U') - max($objT3->format('U'), $objT1->format('U'));
    		}
    		elseif ($datedmY == $dmY2 && $datedmY != $dmY1 && $objT3 < $objT2) { // dernier jour de la période et plage commencant avant la fin
    			$temps += min($objT4->format('U'), $objT2->format('U')) - $objT3->format('U');
    		}
    	}
    	return $temps;
    }
     
    $plages_we[] = array('debut'=>'00:00', 'fin'=>'24:00');
    $plages_semaine[] = array('debut'=>'00:00', 'fin'=>'07:30');
    $plages_semaine[] = array('debut'=>'20:00', 'fin'=>'24:00');
    $total = array('we'=>0, 'semaine'=>0);
     
    $duree = 60;
    $objT1 = date_create('2014-02-23 23:20');
    $objT2 = date_create('2014-02-23 23:20 +'  . $duree . ' minute');
     
     
    for ($date = clone $objT1; $date->format('Ymd') <= $objT2->format('Ymd'); $date->modify('+1 day')) {
    	if ($date->format('N') > 5) {
    		$total['we'] += delai_plage($objT1, $objT2, $date, $plages_we);
    	}
    	else {
    		$total['semaine'] +=delai_plage($objT1, $objT2, $date, $plages_semaine);
    	} 
    }
     
    print_r($total); // attention c'est des secondes.
    Ce principe doit être plus efficace que de regarder minute par minute.
    Dans tes tests pense a contrôler le comportement aux alentours des changements d'heures été/hiver.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  9. #9
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut
    Exemple : Sachant que la limite est à 7h30, une personne commençant à 6h pour un astreinte 1h10, devrait être payée 2h, mais n'est payée que 1h30 vu que la dernière demi-heure de l'heure entamée tombe dans les horaires non payé.
    La personne DEVRAIT être payé 2h, mais MON CODE ACTUEL ne la paye que 1h30 car la dernière demi-heure tombe en non payé je m'étais mal exprimé

    Le passage heure été/hiver merci de m'y faire penser !

    Le système minute par minute me convient bien car généralement une astreinte pour ma boite ne dure grand maximum qu'aux alentours de 4h ... Mais je vais quand même essayer de comprendre le fonctionnement de ton code jour par jour ça pourrait m'inspirer de nouvelles idées pour le chevauchement

    Encore merci de m'aider !

  10. #10
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Ca fait bien 70 minutes de travail.
    Et heure_entammee(70) donne bien 120.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  11. #11
    Membre à l'essai
    Femme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Janvier 2013
    Messages : 40
    Points : 22
    Points
    22
    Par défaut
    Problème réglé !

    Mon souci venait du fait que heure_entamee était effectué avant la définition de la plage ...

    Donc par exemple AVEC LE CODE QUE J'AVAIS une intervention débutant à 7h pour une durée de 20 minute :
    - la durée passait dans heure_entamee et devenait 60 minute.
    - puis la définition de la plage horaire avec plage_facturation donnait : Array ( [0] => 30 [1] => 30 [2] => 0 [3] => 0 ) car la limite est 7h30
    - donc avec la fonction tarification seulement 30 minute étaient payé.


    j'ai donc modifié la fonction tarification comme ci-dessous et maintenant tous les test unitaire qui étaient prévu pour ce code sont passés

    Je met en résolu

    Et une dernière fois merci à toi Sabotage d'avoir pris le temps de m'aider et de m'expliquer clairement les choses ça fait plaisir !

    Le code complet fonctionnant (absolument pas optimisé puisque codé par un débutant ^^) si jamais certains ont besoin d'une fonction similaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    // CONSTANTES DEFINIT DANS /app/Config/bootstrap.php car j'utilise CakePHP
    //define('FACTURATION_NA', 0);
    //define('FACTURATION_SEMAINE', 1);
    //define('FACTURATION_SAMEDI', 2);
    //define('FACTURATION_DIMANCHE', 3);
    // fonction qui donne la période de facturation
    static function plage_facturation($objDate) {
    	$heure = $objDate->format('H:i');
    	$joursem = $objDate->format('N');
    	// lundi - vendredi
    	if ($joursem < 6) {
    	        if ($heure <= '07:29' || $heure >= '20:00') {
    		        return FACTURATION_SEMAINE; 
    		}
    	}
    	// samedi
    	elseif ($joursem == 6){
    		return FACTURATION_SAMEDI;
    	}
    	// dimanche
    	elseif ($joursem == 7){
    		return FACTURATION_DIMANCHE;
    	}
    	return FACTURATION_NA;
    }
    // fonction qui ajoute les heures entamées
    static function heure_entammee($duree) {
    	if ($duree <= 240){
    	        if (($duree%60) != 0){
    		        $duree = $duree - ($duree%60) + 60;
    		}
    	}
    	else {
    		$reste = $duree - 240;
    		if (($reste%120) != 0){
    		        $duree = $duree - ($reste%120) + 120;
    		}
    	}
    	return $duree;
    }
    static function tarification($facturation, $jourDepart) {
    	if ((($facturation[1]%60) != 0) && (empty($facturation[2]))){
            	$facturation[1] = $facturation[1] - ($facturation[1]%60) + 60;
       	 }
       	 if ((empty($facturation[3]) == false) && (empty($facturation[0]) == false) && (($facturation[3] + $facturation[1])%60 != 0)){
    		$facturation[1] = $facturation[1] - (($facturation[3] + $facturation[1])%120) + 120;
    	}
    	if ($jourDepart < 6) {
    		$tarification = 35 + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
    		return $tarification;
    	}elseif ($jourDepart == 6){
    		$tarification = (35*1.2) + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
    		return $tarification;
    	}elseif ($jourDepart == 7){
    		$tarification = (35*1.5) + ($facturation[1]*(35/60)) + ($facturation[2]*((35/60)*1.2)) + ($facturation[3]*((35/60)*1.5));
    		return $tarification;
    	}
    }
    static function calculTarif($datedebut, $duree){
    	// traitement
    	$objDate = date_create($datedebut);
    	$jourDepart = $objDate->format('N');
    	$duree = $duree;
    	$dureePayee = Post::heure_entammee($duree);
    	$facturation = array(FACTURATION_NA=>0, FACTURATION_SEMAINE=>0, FACTURATION_SAMEDI=>0, FACTURATION_DIMANCHE=>0);
    	for ($i = 0; $i < $dureePayee; $i++) {
    		$plage_facturation = Post::plage_facturation($objDate);
    		if (Post::plage_facturation($objDate) !== FALSE) {
    			$facturation[$plage_facturation]++;
    		}
    		$objDate->modify('+1 minute');
    	}
    	// résultat 
    	$prix = Post::tarification($facturation, $jourDepart);
    	return ceil($prix);
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Imbrication de fonction avec calcul sur date
    Par blazko49 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 28/01/2013, 15h19
  2. Réponses: 6
    Dernier message: 05/01/2009, 10h18
  3. Réponses: 6
    Dernier message: 12/01/2008, 18h21
  4. Fonction de calcul du nb de jour entre 2 dates
    Par Teugos dans le forum SAP
    Réponses: 3
    Dernier message: 20/09/2007, 18h12
  5. [Date] Fonction de calcul de durée entre 2 dates
    Par jesus144 dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 10/01/2006, 16h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo