Jours ouvrés entre 2 dates

Bonsoir,

Je vais peut-être faire réagir beaucoup de personnes par ma demande, mais comme je ne comprends pas trop le fonctionnement, je me lance.

J’ai trouvé 1 script en PHP permettant de calculer les jours ouvrés entre 2 dates défini. Sauf que je n’arrive pas à comprendre comment mettre le script en place dans Jeedom, faut-il déjà que j’utilise le plugin Script ?

Puis comment je fais pour mettre la date de début et la date de fin pour que Jeedom m’affiche le nombre de jours ouvrés ??

Désolé, vu mon incompétence, si je hérisse le poil de certain, mais je pense que ce script va certainement intéresser du monde.

<?php
// Fonction permettant de compter le nombre de jours ouvrés entre deux dates
function get_nb_open_days($date_start, $date_stop) {	
	$arr_bank_holidays = array(); // Tableau des jours feriés	
	
	// On boucle dans le cas où l'année de départ serait différente de l'année d'arrivée
	$diff_year = date('Y', $date_stop) - date('Y', $date_start);
	for ($i = 0; $i <= $diff_year; $i++) {			
		$year = (int)date('Y', $date_start) + $i;
		// Liste des jours feriés
		$arr_bank_holidays[] = '1_1_'.$year; // Jour de l'an
		$arr_bank_holidays[] = '1_5_'.$year; // Fete du travail
		$arr_bank_holidays[] = '8_5_'.$year; // Victoire 1945
		$arr_bank_holidays[] = '14_7_'.$year; // Fete nationale
		$arr_bank_holidays[] = '15_8_'.$year; // Assomption
		$arr_bank_holidays[] = '1_11_'.$year; // Toussaint
		$arr_bank_holidays[] = '11_11_'.$year; // Armistice 1918
		$arr_bank_holidays[] = '25_12_'.$year; // Noel
				
		// Récupération de paques. Permet ensuite d'obtenir le jour de l'ascension et celui de la pentecote	
		$easter = easter_date($year);
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + 86400); // Paques
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + (86400*39)); // Ascension
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + (86400*50)); // Pentecote	
	}
	//print_r($arr_bank_holidays);
	$nb_days_open = 0;
	// Mettre <= si on souhaite prendre en compte le dernier jour dans le décompte	
	while ($date_start < $date_stop) {
		// Si le jour suivant n'est ni un dimanche (0) ou un samedi (6), ni un jour férié, on incrémente les jours ouvrés	
		if (!in_array(date('w', $date_start), array(0, 6)) 
		&& !in_array(date('j_n_'.date('Y', $date_start), $date_start), $arr_bank_holidays)) {
			$nb_days_open++;		
		}
		$date_start = mktime(date('H', $date_start), date('i', $date_start), date('s', $date_start), date('m', $date_start), date('d', $date_start) + 1, date('Y', $date_start));			
	}		
	return $nb_days_open;
}

// Exemple : Du 11 au 15 juillet il n'y a qu'un jour ouvré (week-end + 1 jours férié)
$date_depart = strtotime('2008-07-11');
$date_fin = strtotime('2008-07-15');
$nb_jours_ouvres = get_nb_open_days($date_depart, $date_fin);
echo 'Il y a '.$nb_jours_ouvres.' jours ouvrés entre le '.date('d/m/Y', $date_depart).' et le '.date('d/m/Y', $date_fin);
?>

Salut,

Tu peux l’adapter légèrement pour le rendre utilisable dans un scénario. Tu peux même incorporer ce code dans le fichier user.function.class.php.

Après il va falloir récupérer le résultat dans une commande j’imagine ? Ou c’est pour utiliser dans un autre scénario auquel cas une variable suffira ? Bref quel est le but final ?

Je couche les monstres dans pas trop longtemps et je regarde ça…

Salut Salvialf,

Merci de me répondre aussi rapidement, mais je pense que tu vas devoir m’expliquer un peu plus que cela. Mon but est juste de faire mon décompte avant mon départ à la retraite, un petit kif perso…

Déjà pour incorporer ce code dans user.function.class.php je fais comment?
Je me connecte en SSH et j’utilise nano?

Tu veux afficher le résultat chaque jour dans Jeedom ? Sur le dashboard ou dans un design ?

Genre un message : « Il reste XX jours avant la retraite »

Je vais te préparer tout ça ne t’inquiètes pas il faut juste que je comprenne d’abord quelle utilisation tu souhaites en faire.

C’est exactement ça, m’afficher « il reste xx jours avant la retraite » dans un design

Merci beaucoup

J’avais également trouvé ce code là!


//calcul des années bissextiles
    function leap_year($year){
        return date("L", mktime(0, 0, 0, 1, 1, $year));
    }
//calcul des jours non-ouvrés
function sort_closed_days( $timestamp1, $timestamp2 )
{

//dates en jours de l'année ( depuis le 1er jan )
$date1 = date("z", $timestamp1) ; // date de depart
$date2 = date("z", $timestamp2) ; //date d'arrivée

$day_stamp = 86400 ; //(3600 * 24 ); // un journée en timestamp

//années des deux dates
$year1        = date("Y", $timestamp1) ;
$year2        = date("Y", $timestamp2) ;


$num = 0; //nombre de jours feries a compter sur la duree totale
$counter = 0; 
// la durée entre les deux date, sur l'année en cours ou sur plusieurs années

$year = $year1; // l'année en cours ( defaut : $year1 )


//on calcule le nombre de jours de difference entre les deux dates, en tenant
// compte des années
while ( $year <= $year2 )
{

//on liste les jours fériés de l'année en cours    
$easterDate        = easter_date($year) ;
$easterDay        = date('j', $easterDate) ;
$easterMonth    = date('n', $easterDate) ;
$easterYear        = date('Y', $easterDate) ;
        
            
//le tableau sort les jours fériés de l'année depuis le premier janvier
$closed = array
(
// dates fixes
date("z", mktime(0, 0, 0, 1,  1,  $year))+1,  // 1er janvier
date("z", mktime(0, 0, 0, 5,  1,  $year))+1,  // Fête du travail
date("z", mktime(0, 0, 0, 5,  8,  $year))+1,  // Victoire des alliés
date("z", mktime(0, 0, 0, 7,  14, $year))+1,  // Fête nationale

date("z", mktime(0, 0, 0, 8,  15, $year))+1,  // Assomption
date("z", mktime(0, 0, 0, 11, 1,  $year))+1,  // Toussaint
date("z", mktime(0, 0, 0, 11, 11, $year))+1,  // Armistice
date("z", mktime(0, 0, 0, 12, 25, $year))+1,  // Noel

// Dates basées sur Paques
date("z", mktime(0, 0, 0, $easterMonth, $easterDay + 2, $easterYear))+1, // lundi de Paques
date("z", mktime(0, 0, 0, $easterMonth, $easterDay + 40, $easterYear))+1, // Ascension
date("z", mktime(0, 0, 0, $easterMonth, $easterDay + 50, $easterYear))+1, // Dimanche Pentecote
date("z", mktime(0, 0, 0, $easterMonth, $easterDay + 51, $easterYear))+1 // Lundi de Pentecote
);

		
//si c'est la première année -> on commence par la date de depart; le compteur
// compte les jours jusqu'au 31dec
if( $year == $year1 && $year < $year2 ){ $i = $date1; $counter +=  (
365+leap_year($year) ) - $date1 ; } ;


// si c'est ni la première ni la derniere année -> on commence au premier
// janvier; le compteur compte tous les jours de l'année
if( $year > $year1 && $year < $year2 ){ $i = date("z", mktime(0, 0, 
0, 1,  1,  $year));  $counter += 365+leap_year($year); } ;


// si c'est la dernière année -> on commence au premier janvier; le compteur va
// jusqu'a la date d'arrivée
if( $year == $year2 && $year > $year1 ){ $i = date("z", mktime(0, 0,
0, 1,  1,  $year)); $counter += $date2 ; } ;

// si les deux dates sont dans la même année
if( $year == $year1 && $year == $year2 ){ $i = $date1; $counter += 
$date2 ; } ;

//on boucle les jours sur la période donnée pour cette année
while ( $i < $counter )
{
//on compte chaque jour férié
if( in_array($i, $closed) ) $num++;

//on compte chaque samedi
if( date("w", $timestamp1 + $i * $day_stamp) == 6  && !in_array(
$i, $closed) ) $num++ ;
	
//et chaque dimanche
if( date("w", $timestamp1 + $i * $day_stamp) == 0 && !in_array(
$i, $closed) ) $num++ ;

$i++;
}

$year++ ; // on incremente l'année
}

return $num;
}

Alors la manière la plus simple à mettre en oeuvre :

1. Le scénario

Tu peux mettre en place un scénario programmé chaque jour à 4h10 par exemple :

avec ce bloc code à exécuter :

/* Date de fin au format ANNEE-MOIS-JOUR (Exemple: 2028-07-15 = 15 juillet 2028 */
$date_retraite = '2028-07-15';
/********************************************************************************/
$date_depart = strtotime(date('Y-m-d')); // Date du jour
$date_fin = strtotime($date_retraite); 
$nb_jours_ouvres = get_nb_open_days($date_depart, $date_fin);
$scenario->setLog('Il y a '.$nb_jours_ouvres.' jours ouvrés entre le '.date('d/m/Y', $date_depart).' et le '.date('d/m/Y', $date_fin));
$scenario->setLog('Enregistrement variable(jours_retraite) = Il reste ' . $nb_jours_ouvres . ' jours avant la retraite');
$scenario->setData('jours_retraite', 'Il reste ' . $nb_jours_ouvres . ' jours avant la retraite');

// Fonction permettant de compter le nombre de jours ouvrés entre deux dates
function get_nb_open_days($date_start, $date_stop) {	
	$arr_bank_holidays = array(); // Tableau des jours feriés	
	
	// On boucle dans le cas où l'année de départ serait différente de l'année d'arrivée
	$diff_year = date('Y', $date_stop) - date('Y', $date_start);
	for ($i = 0; $i <= $diff_year; $i++) {			
		$year = (int)date('Y', $date_start) + $i;
		// Liste des jours feriés
		$arr_bank_holidays[] = '1_1_'.$year; // Jour de l'an
		$arr_bank_holidays[] = '1_5_'.$year; // Fete du travail
		$arr_bank_holidays[] = '8_5_'.$year; // Victoire 1945
		$arr_bank_holidays[] = '14_7_'.$year; // Fete nationale
		$arr_bank_holidays[] = '15_8_'.$year; // Assomption
		$arr_bank_holidays[] = '1_11_'.$year; // Toussaint
		$arr_bank_holidays[] = '11_11_'.$year; // Armistice 1918
		$arr_bank_holidays[] = '25_12_'.$year; // Noel
				
		// Récupération de paques. Permet ensuite d'obtenir le jour de l'ascension et celui de la pentecote	
		$easter = easter_date($year);
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + 86400); // Paques
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + (86400*39)); // Ascension
		$arr_bank_holidays[] = date('j_n_'.$year, $easter + (86400*50)); // Pentecote	
	}
	//print_r($arr_bank_holidays);
	$nb_days_open = 0;
	// Mettre <= si on souhaite prendre en compte le dernier jour dans le décompte	
	while ($date_start < $date_stop) {
		// Si le jour suivant n'est ni un dimanche (0) ou un samedi (6), ni un jour férié, on incrémente les jours ouvrés	
		if (!in_array(date('w', $date_start), array(0, 6)) 
		&& !in_array(date('j_n_'.date('Y', $date_start), $date_start), $arr_bank_holidays)) {
			$nb_days_open++;		
		}
		$date_start = mktime(date('H', $date_start), date('i', $date_start), date('s', $date_start), date('m', $date_start), date('d', $date_start) + 1, date('Y', $date_start));			
	}		
	return $nb_days_open;
}

La seule chose à faire sera de renseigner la date que tu souhaites sur la ligne $date_retraite à la place de 2028-07-15 sur la seconde ligne du code :

/* Date de fin au format ANNEE-MOIS-JOUR (Exemple: 2028-07-15 = 15 juillet 2028 */
$date_retraite = '2028-07-15';
/********************************************************************************/

Le résultat sera sauvegardé dans la variable jours_retraite que tu peux consulter via le menu Outils->Variables.

2. Le virtuel

A l’aide du plugin Virtuel, tu ajoutes une commande info virtuelle de type Info/Autre en appelant la variable variable(jours_retraite) dans le champs Calcul de la colonne Valeur :
image

3. Le résultat

image


Le must serait d’inclure la fonction dans le fichier user.function.class.php et de l’appeler directement dans un virtuel programmé par un cron et de se passer du scénario mais c’est plus complexe à mettre en place et à suivre.

J’espère que ça va t’aider, n’hésites pas si tu as besoin de précisions

3 « J'aime »

Alors là super!!! vu le détail il y a plus qu’a tester ça, merci beaucoup je te tiens au courant.

Sa fonctionne, impeccable merci beaucoup, du coup je vais ajouter mes journées de congés prévues dans la liste des jours fériés.

Merci beaucoup Salvialf

Avec plaisir !

C’est quand la retraite alors ?

C’est prévu pour le 1er juin de l’année prochaine.

1 « J'aime »

Je m’attendais à ce que tu répondes par un nombre de jours ouvrés :wink:

Par contre je fais comment pour ajouter une date de congé pour 2021
Pour l’année en cour j’ai :

$arr_bank_holidays[] = '21_8_'.$year; // Congé

J’ai pas trop étudié la fonction et je ne suis plus sur le PC mais dans l’idée il faudrait ajouter une condition à cet endroit. Juste après $year = (int)date('Y', $date_start) + $i; par exemple.

Du style :

if ($year == '2021') {
  $arr_bank_holidays[] = '21_8_'.$year; // Congé
}

Mais si tu es à la retraite le 1er juin 2021 les congés du 21 août ne seront pas un problème :yum:

1 « J'aime »

Non le 21 août, c’est pour cette année, c’était juste pour te montrer comment je fais le rajout de mes congés.
Je vais tester avec la condition. Merci

Oui je m’en doutais mais la boutade était trop facile :sweat_smile:

Nickel, sa fonctionne impeccablement, je n’ai pas besoin de plus, merci beaucoup et très pédagogue en plus.

1 « J'aime »

Ce sujet a été automatiquement fermé après 24 heures suivant le dernier commentaire. Aucune réponse n’est permise dorénavant.