PHP funkce pro vyjádření časových intervalů slovně … “včera”, “před 5 dny”, “za rok” …

Jste-li vývojáři, může se vám hodit funkce pro získání slovního vyjádření uplynulého času (nebo zbývajícího času). Informace o uplynulém času, případně o času, který zbývá do nějaké události, se snáze uživatelům zpracovává, je-li vyjádřena slovně jako časový interval.

Představte si, že máte uživatelům zobrazit u jednotlivých akcí i kdy k těmto akcím došlo či dojde. Můžete samozřejmě zobrazit číselně datum a více se tím nezabývat:
14. dubna 2012 ve 13:30:15

Uživatelé by však jistě ocenili, kdyby nemuseli nad datumy přemýšlet a hned dokázali získat představu, kdy daná akce proběhla či proběhne. Zvláště kritické je informovat uživatele srozumitelnějším způsobem například v přehledech o objednávkách v e-shopech.
Ideální je proto zobrazit nejen datum, ale i slovní vyjádření:
včera
před 10 minutami
před týdnem
před měsícem
před 3 měsíci
za rok
za týden
za 10 minut
apod.

<?php
/** -----------------------------------------------------------------------
*     class CasovyInterval
*     Vrací slovní vyjádření uplynulého času nebo zbývajícího času
*     např.: před 5 minutami, před hodinou, před pěti hodinami, včera, před 3 dny, před týdnem, před měsícem, za minutu, za hodinu, ...
*
*     @author   Petr Franěk <franek.petr@seznam.cz>
*     @access   public
*     @todo     kontrola platnosti parametru $datum (např. pomocí preg_match)
*
*     Příklad použití:
*     $datum = '2013-03-05 12:00:12';
*     $t = new CasovyInterval;
*     echo $interval = $t->intervalSlovne($datum);       // zobrazí uplynulý nebo zbývající čas slovně v češtině
*     echo $uplynulychDni = $t->pocetDni('2011-01-01')   // zobrazí počet dní (číselně) od daného datumu
*
*     Třída CasovyInterval nemá konstruktor. Nejde o objekt v pravém slova smyslu. Slouží pouze k zapouzdření funkcí.
*/
class CasovyInterval
{
   /**  ------------------------------------------------------------------------
   *
   *     Konvertuje DATE (YYYY-MM-DD) nebo DATETIME (YYYY-MM-DD hh:mm:ss) na slovní vyjádření uplynulého nebo zbývajícího času
   *
   *     Vrací slovní vyjádření uplynulého nebo zbývajícího času
   *     @param      string datetime
   *     @access     public
   *     @return     string
   */
   public function intervalSlovne($datum)
   {
       if( empty($datum) ) {
           return "Nebyl předán datum.";
       }
 
       $perioda       = array("sekundy", "minuty", "hodiny", "dny", "týdny", "měsíce", "roky");
       $delka         = array("60","60","24","7","4.35","12");
 
       $nyni          = time();
       $unixovy_datum = strtotime($datum);
 
       if( empty($unixovy_datum) ) {
           return "Chybný formát datumu.";
       }
 
       // minulý čas nebo budoucí čas?
       //
       if( $nyni > $unixovy_datum ) {
           $rozdil      = $nyni - $unixovy_datum;
           $slovesnyCas = "před";
 
       } else {
           $rozdil      = $unixovy_datum - $nyni;
           $slovesnyCas = "za";
       }
 
       for($j = 0; $rozdil >= $delka[$j] && $j < count($delka)-1; $j++) {
           $rozdil /= $delka[$j];
       }
 
       $rozdil = round($rozdil);
 
       if( $slovesnyCas == "před" ) {
         switch ($perioda[$j]) {
          case "sekundy":
            if( $rozdil == 1 ) {
                $perioda[$j] = "sekundou";
                $rozdil = "jednou";
            }else{
                $perioda[$j] = "sekundami";
            }
            break;
 
          case "minuty":
            if( $rozdil == 1 ) {
                $perioda[$j] = "minutou";
                $rozdil = "";
            }else{
                $perioda[$j] = "minutami";
            }
            break;  
 
          case "hodiny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "hodinou";
                $rozdil = "";
            }else{
                $perioda[$j] = "hodinami";
            }
            break;  
 
          case "dny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "včera";
                $rozdil = "";
                $slovesnyCas = "";
            }else{
                $perioda[$j] = "dny";
            }
            break;  
 
          case "týdny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "týdnem";
                $rozdil = "";
            }else{
                $perioda[$j] = "týdny";
            }
            break; 
 
          case "měsíce":
            if( $rozdil == 1 ) {
                $perioda[$j] = "měsícem";
                $rozdil = "";
            }elseif( $rozdil == 12 ){
                $perioda[$j] = "rokem";
                $rozdil = "";
            }else{
               $perioda[$j] = "měsíci";
            }
            break; 
 
          case "roky":
            if( $rozdil == 1 ) {
                $perioda[$j] = "rokem";
                $rozdil = "";
            }else{
                $perioda[$j] = "roky";
            }
            break;
          default:
            break;
          }
       }else{    // "za ..."
         switch ($perioda[$j]) {
         case "sekundy":
            if( $rozdil == 1 ) {
                $perioda[$j] = "sekundu";
                $rozdil = "jednu";
            }else{
                $perioda[$j] = "sekund";
            }
            break;
 
          case "minuty":
            if( $rozdil == 1 ) {
                $perioda[$j] = "minutu";
                $rozdil = "";
            }else{
                $perioda[$j] = "minut";
            }
            break;   
 
          case "hodiny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "hodinu";
                $rozdil = "";
            }elseif( $rozdil >= 2 && $rozdil < 5){
               $perioda[$j] = "hodiny";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "hodin";
            }
            break;   
 
          case "dny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "zítra";
                $rozdil = "";
                $slovesnyCas = "";
            }else{
               if( $rozdil > 1 && $rozdil < 5 ) {
                $perioda[$j] = "dny";
               }else{
                  $perioda[$j] = "dní";
               }
            }
            break;   
 
          case "týdny":
            if( $rozdil == 1 ) {
                $perioda[$j] = "týden";
                $rozdil = "";
            }elseif( $rozdil == 2 ){
               $perioda[$j] = "týden";
                $rozdil = "příští";
            }elseif( $rozdil > 2 && $rozdil < 5 ){
               $perioda[$j] = "týdny";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "týdnů";
            }
            break;   
 
          case "měsíce":
            if( $rozdil == 1 ) {
                $perioda[$j] = "měsíc";
                $rozdil = "";
            }elseif( $rozdil >= 2 && $rozdil < 5 ){
               $perioda[$j] = "měsíce";
            }elseif( $rozdil == 12 ){
                $perioda[$j] = "rok";
                $rozdil = "";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "měsíců";
            }
            break;  
 
          case "roky":
            if( $rozdil == 1 ) {
                $perioda[$j] = "rok";
                $rozdil = "";
            }elseif( $rozdil == 2 ){
               $perioda[$j] = "roky";
            }
            break;  
 
          default:
 
            break;
          }
       }
 
       return "{$slovesnyCas} $rozdil $perioda[$j]";
   }
 
   /**  ------------------------------------------------------------------------
   *
   *     Vrací počet dní od parametrem předaného datumu v mysql formátu ... YYYY-mm-dd nebo YYYY-mm-dd HH:ii:ss
   *
   *     @param      string datetime
   *     @access     public
   *     @return     integer
   */
   public function pocetDni($datum = "")
   {
      $sekund = $this->datum_na_timestamp($datum);
 
      $rozdil = time() - $sekund;
      $dni = floor($rozdil / (60 * 60 * 24));
 
    return $dni;
   }
 
   /**  ------------------------------------------------------------------------
   *
   *     Konvertuje DATE (YYYY-MM-DD) nebo DATETIME (YYYY-MM-DD hh:mm:ss) na timestamp
   *
   *     Vrací timestamp
   *     @param      string
   *     @access     private
   *     @return     integer
   */
   private function datum_na_timestamp($datetime = "")
   {
      // použitelné pouze pro 10 nebo 19 znakové vyjádření ( 0000-00-00  nebo 0000-00-00 00:00:00 )
      $delka = strlen($datetime);
 
      if(!($delka == 10 || $delka == 19)) {
         return false;
      }
 
      $datum = $datetime;
      $hours = 0;
      $minutes = 0;
      $seconds = 0;
 
      // DATETIME
      if($delka == 19)
      {
         list($datum, $time) = explode(" ", $datetime);
         list($hodin, $minut, $sekund) = explode(":", $time);
      }
 
      list($rok, $mesic, $den) = explode("-", $datum);
 
      return mktime($hodin, $minut, $sekund, $mesic, $den, $rok);
   }
 
} // end class
 
?>
<?php
/** -----------------------------------------------------------------------
*     class CasovyInterval
*     Vrací slovní vyjádření uplynulého času nebo zbývajícího času
*     např.: před 5 minutami, před hodinou, před pěti hodinami, včera, před 3 dny, před týdnem, před měsícem, za minutu, za hodinu, ...
*
*     @author   Petr Franěk <franek.petr@seznam.cz>
*     @access   public
*     @todo     kontrola platnosti parametru $datum (např. pomocí preg_match)
*
*     Příklad použití:
*     $datum = '2013-03-05 12:00:12';
*     $t = new CasovyInterval;
*     echo $interval = $t->intervalSlovne($datum);       // zobrazí uplynulý nebo zbývající čas slovně v češtině
*     echo $uplynulychDni = $t->pocetDni('2011-01-01')   // zobrazí počet dní (číselně) od daného datumu
*
*     Třída CasovyInterval nemá konstruktor. Nejde o objekt v pravém slova smyslu. Slouží pouze k zapouzdření funkcí.
*/
class CasovyInterval
{
   /**  ------------------------------------------------------------------------
   *
   *     Konvertuje DATE (YYYY-MM-DD) nebo DATETIME (YYYY-MM-DD hh:mm:ss) na slovní vyjádření uplynulého nebo zbývajícího času
   *
   *     Vrací slovní vyjádření uplynulého nebo zbývajícího času
   *     @param      string datetime
   *     @access     public
   *     @return     string
   */
   public function intervalSlovne($datum)
   {
       if( empty($datum) ) {
           return "Nebyl předán datum.";
       }

       $perioda       = array("sekundy", "minuty", "hodiny", "dny", "týdny", "měsíce", "roky");
       $delka         = array("60","60","24","7","4.35","12");

       $nyni          = time();
       $unixovy_datum = strtotime($datum);

       if( empty($unixovy_datum) ) {
           return "Chybný formát datumu.";
       }

       // minulý čas nebo budoucí čas?
       //
       if( $nyni > $unixovy_datum ) {
           $rozdil      = $nyni - $unixovy_datum;
           $slovesnyCas = "před";

       } else {
           $rozdil      = $unixovy_datum - $nyni;
           $slovesnyCas = "za";
       }

       for($j = 0; $rozdil >= $delka[$j] && $j < count($delka)-1; $j++) {
           $rozdil /= $delka[$j];
       }

       $rozdil = round($rozdil);

       if( $slovesnyCas == "před" ) {
       	 switch ($perioda[$j]) {
          case "sekundy":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "sekundou";
            	$rozdil = "jednou";
            }else{
            	$perioda[$j] = "sekundami";
            }
            break;

          case "minuty":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "minutou";
            	$rozdil = "";
            }else{
            	$perioda[$j] = "minutami";
            }
            break;  

          case "hodiny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "hodinou";
            	$rozdil = "";
            }else{
            	$perioda[$j] = "hodinami";
            }
            break;  

          case "dny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "včera";
            	$rozdil = "";
            	$slovesnyCas = "";
            }else{
            	$perioda[$j] = "dny";
            }
            break;  

          case "týdny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "týdnem";
            	$rozdil = "";
            }else{
            	$perioda[$j] = "týdny";
            }
            break; 

          case "měsíce":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "měsícem";
            	$rozdil = "";
            }elseif( $rozdil == 12 ){
              	$perioda[$j] = "rokem";
            	$rozdil = "";
            }else{
               $perioda[$j] = "měsíci";
            }
            break; 

          case "roky":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "rokem";
            	$rozdil = "";
            }else{
            	$perioda[$j] = "roky";
            }
            break;
          default:
          	break;
          }
       }else{    // "za ..."
       	 switch ($perioda[$j]) {
       	 case "sekundy":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "sekundu";
            	$rozdil = "jednu";
            }else{
            	$perioda[$j] = "sekund";
            }
            break;

          case "minuty":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "minutu";
            	$rozdil = "";
            }else{
            	$perioda[$j] = "minut";
            }
            break;   

          case "hodiny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "hodinu";
            	$rozdil = "";
            }elseif( $rozdil >= 2 && $rozdil < 5){
               $perioda[$j] = "hodiny";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "hodin";
            }
            break;   

          case "dny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "zítra";
            	$rozdil = "";
            	$slovesnyCas = "";
            }else{
               if( $rozdil > 1 && $rozdil < 5 ) {
               	$perioda[$j] = "dny";
               }else{
                  $perioda[$j] = "dní";
               }
            }
            break;   

          case "týdny":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "týden";
            	$rozdil = "";
            }elseif( $rozdil == 2 ){
               $perioda[$j] = "týden";
            	$rozdil = "příští";
            }elseif( $rozdil > 2 && $rozdil < 5 ){
               $perioda[$j] = "týdny";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "týdnů";
            }
            break;   

          case "měsíce":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "měsíc";
            	$rozdil = "";
            }elseif( $rozdil >= 2 && $rozdil < 5 ){
               $perioda[$j] = "měsíce";
            }elseif( $rozdil == 12 ){
            	$perioda[$j] = "rok";
            	$rozdil = "";
            }elseif( $rozdil >= 5 ){
               $perioda[$j] = "měsíců";
            }
            break;  

          case "roky":
            if( $rozdil == 1 ) {
            	$perioda[$j] = "rok";
            	$rozdil = "";
            }elseif( $rozdil == 2 ){
               $perioda[$j] = "roky";
            }
            break;  

          default:

          	break;
          }
       }

       return "{$slovesnyCas} $rozdil $perioda[$j]";
   }

   /**  ------------------------------------------------------------------------
   *
   *     Vrací počet dní od parametrem předaného datumu v mysql formátu ... YYYY-mm-dd nebo YYYY-mm-dd HH:ii:ss
   *
   *     @param      string datetime
   *     @access     public
   *     @return     integer
   */
   public function pocetDni($datum = "")
   {
      $sekund = $this->datum_na_timestamp($datum);

      $rozdil = time() - $sekund;
      $dni = floor($rozdil / (60 * 60 * 24));

   	return $dni;
   }

   /**  ------------------------------------------------------------------------
   *
   *     Konvertuje DATE (YYYY-MM-DD) nebo DATETIME (YYYY-MM-DD hh:mm:ss) na timestamp
   *
   *     Vrací timestamp
   *     @param      string
   *     @access     private
   *     @return     integer
   */
   private function datum_na_timestamp($datetime = "")
   {
      // použitelné pouze pro 10 nebo 19 znakové vyjádření ( 0000-00-00  nebo 0000-00-00 00:00:00 )
      $delka = strlen($datetime);

      if(!($delka == 10 || $delka == 19)) {
         return false;
      }

      $datum = $datetime;
      $hours = 0;
      $minutes = 0;
      $seconds = 0;

      // DATETIME
      if($delka == 19)
      {
         list($datum, $time) = explode(" ", $datetime);
         list($hodin, $minut, $sekund) = explode(":", $time);
      }

      list($rok, $mesic, $den) = explode("-", $datum);

      return mktime($hodin, $minut, $sekund, $mesic, $den, $rok);
   }

} // end class

?>

class.casovy_interval.zip – zdrojový soubor

Funkce zapouzdřeny do třídy CasovyInterval. Třídu můžete používat ve svých projektech.

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *