[PHP 5] Classe Date

Eléphant du PHP | 281 Messages

21 déc. 2005, 15:31

Bonjour,

Op une petite classe Date que je viens de faire. Certes c'est assez basique et assez spécifique à ce dont j'ai besoin pour le moment mais ça peut toujours être utile à certains d'entre nous/vous :wink:

Si jamais j'implémente d'autres fonctions et que ça vous intéresse, je mettrai à jour la classe :

Version statique :
<?php
	/**
	 * Classe Date
	 * -----------
	 * Permet d'effectuer des p'tits calculs a partir d'une date
	 * --------------------------
	 * @author Ouaibou (Laurent.P)
	 * @version 2005.12.21
	 */
	 
	class Date {
		
		/**
		 * Converti une date au format aaaa-mm-jj hh:mm:ss dans
		 * un format souhaite
		 *
		 * @param String $date Date a convertir au format aaaa-mm-jj hh:mm:ss
		 * @param String $format Nouveau format de date voulu
		 * @see dateToTimestamp()
		 * @return String Renvoie la date dans le nouveau format
		 */
	
		static public function conversionFormat($date, $format="d/m/Y H:i:s")
		{		
			return date($format, self::dateToTimestamp($date));
		}
		
		/**
		 * Converti une date au format aaaa-mm-jj hh:mm:ss en un timestamp
		 * 
		 * @param String $date Date a convertir au format aaaa-mm-jj hh:mm:ss
		 * @return int Renvoie la date en timestamp
		 */
	
		static public function dateToTimestamp($date)
		{
			list($annee, $mois, $jour, $heure, $minute, $seconde) = sscanf($date, "%d-%d-%d %d:%d:%d");
			
			return mktime($heure, $minute, $seconde, $mois, $jour, $annee);
		}
		
		/**
		 * @return String Renvoie la date du jour au format francais
		 */
		 
		static public function fr()
		{
			$jour = array("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi");
			$mois = array("Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
			
			return $jour[date(w)]." ".date(j)." ".$mois[date(n)-1]." ".date(Y);
		}
		
		/**
		 * Calcule le temps ecoule entre deux dates en jours/heures/minutes/secondes
		 * 
		 * @param String $date1 Date au format aaaa-mm-jj hh:mm:ss
		 * @param String $date2 Date au format aaaa-mm-jj hh:mm:ss
		 * @return String Renvoie le temps ecoule entre les deux dates dans un tableau associatif
		 */
		
		static public function tempsEcoule($date1, $date2)
		{
			$timestamp1 = self::dateToTimestamp($date1);
			$timestamp2 = self::dateToTimestamp($date2);
			
			$difference = $timestamp1 - $timestamp2;
			
			if($difference < 0)
				$difference = $timestamp2 - $timestamp1;
			
			// Calcul du nombre de jours
			$reste = $difference % 86400;
			$nb_jours = ($difference - $reste) / 86400;
			 
			// Calcul du nombre d'heures
			$difference = $reste;
			$reste = $difference % 3600;
			$nb_heures = (int)(($difference - $reste) / 3600);

			// Calcul du nombre de minutes
			$difference = $reste;
			$reste = $difference % 60;
			$nb_minutes = ($difference - $reste) / 60;
			
			$nb_secondes = $reste;
			
			// Création du tableau associatif
			
			$tab['jours'] = $nb_jours;
			$tab['heures'] = $nb_heures;
			$tab['minutes'] = $nb_minutes;
			$tab['secondes'] = $nb_secondes;
			
			return $tab;
		}			
	}
?>
Version non-statique :
<?php
	/**
	 * Classe Date
	 * -----------
	 * Permet d'effectuer des p'tits calculs a partir d'une date
	 * --------------------------
	 * @author Ouaibou (Laurent.P)
	 * @version 2005.12.21
	 */
	 
	class Date {
		
		private $date;
		
		/**
		 * Cre un nouvel objet date
		 *
		 *@param String $date Date de base au format aaaa-mm-jj hh:mm:ss
		 */
		
		public function __construct($date)
		{
			$this->date = $date;
		}
		
		/**
		 * Modifie la valeur de la date de base
		 *
		 * @param String $date Date de base au format aaaa-mm-jj hh:mm:ss
		 */
		
		public function setDate($date)
		{
			$this->date = $date;
		}
		
		/**
		 * Converti une date au format aaaa-mm-jj hh:mm:ss dans
		 * un format souhaite
		 *
		 * @param String $date Date a convertir au format aaaa-mm-jj hh:mm:ss
		 * @param String $format Nouveau format de date voulu
		 * @see dateToTimestamp()
		 * @return String Renvoie la date dans le nouveau format
		 */
	
		public function conversionFormat($format="d/m/Y H:i:s")
		{		
			return date($format, $this->dateToTimestamp($this->$date));
		}
		
		/**
		 * Converti une date au format aaaa-mm-jj hh:mm:ss en un timestamp
		 * 
		 * @param String $date Date a convertir au format aaaa-mm-jj hh:mm:ss
		 * @return int Renvoie la date en timestamp
		 */
	
		public function dateToTimestamp()
		{
			list($annee, $mois, $jour, $heure, $minute, $seconde) = sscanf($this->date, "%d-%d-%d %d:%d:%d");
			
			return mktime($heure, $minute, $seconde, $mois, $jour, $annee);
		}
		
		/**
		 * @return String Renvoie la date du jour au format francais
		 */
		 
		public function fr()
		{
			$jour = array("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi");
			$mois = array("Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
			
			return $jour[date(w)]." ".date(j)." ".$mois[date(n)-1]." ".date(Y);
		}
		
		/**
		 * Calcule le temps ecoule entre deux dates en jours/heures/minutes/secondes
		 * 
		 * @param String $date Date au format aaaa-mm-jj hh:mm:ss
		 * @return String Renvoie le temps ecoule entre la date de base et celle entree dans un tableau associatif
		 */
		
		public function tempsEcoule($date)
		{
			$timestamp1 = $this->dateToTimestamp($this->date);
			$timestamp2 = $this->dateToTimestamp($date);
			
			$difference = $timestamp1 - $timestamp2;
			
			if($difference < 0)
				$difference = $timestamp2 - $timestamp1;
			
			// Calcul du nombre de jours
			$reste = $difference % 86400;
			$nb_jours = ($difference - $reste) / 86400;
			 
			// Calcul du nombre d'heures
			$difference = $reste;
			$reste = $difference % 3600;
			$nb_heures = (int)(($difference - $reste) / 3600);

			// Calcul du nombre de minutes
			$difference = $reste;
			$reste = $difference % 60;
			$nb_minutes = ($difference - $reste) / 60;
			
			$nb_secondes = $reste;
			
			// Création du tableau associatif
			
			$tab['jours'] = $nb_jours;
			$tab['heures'] = $nb_heures;
			$tab['minutes'] = $nb_minutes;
			$tab['secondes'] = $nb_secondes;
			
			return $tab;
		}			
	}
?>
@+
Modifié en dernier par Ouaibou le 21 déc. 2005, 18:35, modifié 3 fois.

Mammouth du PHP | 19672 Messages

21 déc. 2005, 16:33

J'ai une question/remarque :
// Verification de retour
            
            if($nb_jours == 0)
                return $nb_heures." heures ".$nb_minutes." minutes ".$nb_secondes." secondes";
            elseif($nb_jours == 0 && $nb_heures == 0)
                return $nb_minutes." minutes ".$nb_secondes." secondes";
            elseif($nb_jours == 0 && $nb_heures == 0 && $nb_minutes == 0)
                return $nb_secondes." secondes";
            else
                return $nb_jours." jours ".$nb_heures." heures ".$nb_minutes." minutes ".$nb_secondes." secondes";
        }
Si je me fie a cette partie du code, dans le cas où $nb_jours est égal à 0, ça ne dépassera jamais le premier if pour vérifier une éventuelle seconde condition sur le nombre d'heures ou le nombre de minutes... :-k
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

21 déc. 2005, 16:51

J'aurais passé tout ça en non-statique, pour profiter un peu plus du modèle objet. Je l'avais même fait, mais j'ai du tomber dans un trou noir mon message n'a semble-t-il pas été pris en compte, et je n'ai pas le courage de tout retaper...

Je modifierais la structure de la classe pour que les fonctions ne soient pas statiques, je généraliserais les fonctions (calcul de différence entre deux dates plutot qu'entre une date et now), et je ferais renvoyer à la fonction de calcul de différence un tableau de valeurs (plus manipulable) plutot qu'un texte en français.

Eléphant du PHP | 281 Messages

21 déc. 2005, 18:04

Sur vos suggestion et remarques (en vous remerciant) j'ai fait quelques modifications :

- Correction de certaines infos de documentations fausses
- Temps écoulé entre deux dates
- Retour du temps écoulé dans un tableau associatif (du coup ta question Cyrano ne se pose plus, tant mieux car après réflexion je penses que t'avais raison)

Voilou voila, par contre j'ai laissé le tout statique. Je penses qu'ensuite le fait de mettre statique non statique dépend surtout de l'utilisation qu'on en fait. Mais si quelqu'un saurait m'expliquer l'avantage de mettre en non-statique pourquoi pas ;)

@+

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

21 déc. 2005, 18:11

Aucun avantage particulier immédiat à passer en non-statique, et surtout si tu utilises ça comme un set de fonctions. C'est simplement que tant qu'à faire une classe, plutot que de déguiser une série de fonction en classe, autant faire un objet ;)
// Version actuelle
$aujourdhui = date('d-m-Y H:i:s');
$hier = date('d-m-Y H:i:s', time()-24*3600);
echo Date::conversionFormat($aujourdhui);
echo " - ", Date::conversionFormat($hier);
echo " = ", Date::tempsEcoule($aujourdhui, $hier);

// Version objet
$aujourdhui = new Date();
$hier = new Date(time()-24*3600);
echo $aujourdhui->conversionFormat();
echo " - ", $hier->conversionFormat();
echo " = ", $aujourdhui->tempsEcoule($hier);
Dans le second cas on manipule bien des objets de la classe date, dans le premier cas la classe n'a aucun intérêt. Dans le second cas on pourra s'autoriser des méthodes très complexes, manipulant de nombreux attributs qu'on pourra cacher dans l'objet.

Edit : voici comment je la modifierais rapidement
<?php

define('INT_SECONDE', 1);
define('INT_MINUTE', 60*INT_SECONDE);
define('INT_HEURE', 60*INT_MINUTE);
define('INT_JOUR', 24*INT_HEURE);
define('INT_SEMAINE', 7*INT_JOUR);

class Date {
    
    private $timestamp;
    public $formatSQL = "Y-m-d H:i:s";
    public $formatParDefaut = "d/m/Y H:i:s";
    
    // arguments acceptés :
    // - un timestamp
    // - une date au format "SQL" par défaut : "Y-m-d H:i:s"
    // - rien du tout (valeur par défaut) = le temps actuel
    public function __construct($valeur = null)
    {
        // calcul du masque pcre
        $masque = str_replace(
            array('Y','m','d','H','i','s'),
            array('\d+','\d+','\d+','\d+','\d+','\d+'),
            $this->formatSQL);
        if (preg_match("/$masque/", $valeur, $m))
            $this->fromSQL($m[0]);
        else
            $this->fromUNIX($valeur);
    }

    // ajoute un intervalle de temps construit avec les constantes INT_*
    public function ajouteIntervalle($intervalle)
    {
        $this->timestamp = max(0, $this->timestamp+$intervalle);
    }
    
    // timestamp Unix de la date
    public function tempsUNIX()
    {
        return $this->timestamp;
    }

    public function fromSQL($dateFormatSQL) 
    {
        // calcul du masque scanf
        $masque = str_replace(
            array('Y','m','d','H','i','s'),
            array('%d','%d','%d','%d','%d','%d'),
            $this->formatSQL);
        list($annee, $mois, $jour, $heure, $minute, $seconde) = sscanf($date, $masque);
        return mktime($heure, $minute, $seconde, $mois, $jour, $annee);
    }

    public function fromUNIX($timestamp = null)
    {
        $this->timestamp = $timestamp!==null ? intval($timestamp) : time();
    }
    
    public function toString($format = null)
    {
        if ($format===null)
            $format = $this->formatParDefaut;
        return date($format, $this->timestamp);
    }

    public function fr()
    {
        $jour = array("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi");
        $mois = array("Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
        list($w,$j,$n,$Y) = explode(' ', $this->toString('w j n Y'));
        return $jour[$w]." ".$j." ".$mois[$n-1]." ".$Y;
    }
        
    public function difference($date)
    {
        $difference = abs($this->tempsUNIX()-$date->tempsUNIX());
        // Calcul du nombre de jours
        $reste = $difference % 86400;
        $nb_jours = ($difference - $reste) / 86400;
        // Calcul du nombre d'heures
        $difference = $reste;
        $reste = $difference % 3600;
        $nb_heures = (int)(($difference - $reste) / 3600);
        // Calcul du nombre de minutes
        $difference = $reste;
        $reste = $difference % 60;
        $nb_minutes = ($difference - $reste) / 60;
        $nb_secondes = $reste;
        // Création du tableau associatif
        $tab['jours'] = $nb_jours;
        $tab['heures'] = $nb_heures;
        $tab['minutes'] = $nb_minutes;
        $tab['secondes'] = $nb_secondes;
        return $tab;
    }            

}

?>
Exemple :
$aujourdhui = new Date();
// hier *presque* à la même heure : -2h +45s
$hier = new Date();
$hier->ajouteIntervalle(-1*INT_JOUR-2*INT_HEURE+45*INT_SECONDE);
// différence de dates
$diff = $hier->difference($aujourdhui);
// résultat
echo "entre le ", $aujourdhui->fr(), " et le ", $hier->fr(), " se sont ecoulé : ";
echo $diff['secondes'], " seconde(s), ", $diff['minutes'], " minute(s), ", $diff['heures'], " heure(s), ", $diff['jours'], " jour(s).";
entre le Mercredi 21 Décembre 2005 et le Mardi 20 Décembre 2005 se sont ecoulé : 15 seconde(s), 59 minute(s), 1 heure(s), 1 jour(s).
Rien que ne sache faire la version originale, mais on voit rapidement qu'on peut se permettre plus de chose grâce aux attributs d'objets (ici un seul : $timestamp). En plus au lieu de se trimballer un "$aujourdhui" et un "$hier" qui *représentent* une date sous forme de chaine, là on manie des objets, qui *sont* des dates parce qu'on les a conçus ainsi.
Modifié en dernier par naholyr le 21 déc. 2005, 18:59, modifié 4 fois.

Eléphant du PHP | 281 Messages

21 déc. 2005, 18:33

Oui je suis tout à fait d'accord sur ce principe et je penses l'avoir compris mais pour moi le fait de le faire statique c'est un gain d'une ligne (oui bon c'est pas énorme) et donc un objet en moins étant donné que je suis en train de développer un site "totalement objet".

Après il est clair qu'une version non statique peut être interessant pour une utilisation approfondi comme tu l'as dit.

Bref tu m'as donné envie d'écrire la version non-statique (cf : plus haut :D)

@+

Mammouth du PHP | 19672 Messages

21 déc. 2005, 18:47

Il y a une erreur sur une variable dans ta classe Naholyr (ligne 77):
$nb_heures = (int)(($difference - $residu) / 3600);
devrait être:
$nb_heures = (int)(($difference - $reste) / 3600);
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

21 déc. 2005, 19:00

Corrigé, j'ai corrigé celle de ouaibou aussi en passant

Eléphant du PHP | 441 Messages

21 déc. 2005, 23:56

salut à tous,
sur developpez.com certains avaient déjà proposé une classe assez complète. C'est juste pour info
http://www.developpez.net/forums/viewto ... 64#1651864 :wink:
Futures Stars par ici >> www.apel-doorn.com
fan d'info et du ... PSG !! :D
Apprendre, comprendre et maîtriser telle est ma devise!
Fan inconditionnel de netvibes