home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Date / Span.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  33.2 KB  |  1,083 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
  3.  
  4. // {{{ Header
  5.  
  6. /**
  7.  * Generic time span handling class for PEAR
  8.  *
  9.  * PHP versions 4 and 5
  10.  *
  11.  * LICENSE:
  12.  *
  13.  * Copyright (c) 1997-2005 Leandro Lucarella, Pierre-Alain Joye
  14.  * All rights reserved.
  15.  *
  16.  * Redistribution and use in source and binary forms, with or without
  17.  * modification, are permitted under the terms of the BSD License.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22.  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23.  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  29.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * @category   Date and Time
  33.  * @package    Date
  34.  * @author     Leandro Lucarella <llucax@php.net>
  35.  * @author     Pierre-Alain Joye <pajoye@php.net>
  36.  * @copyright  1997-2006 Leandro Lucarella, Pierre-Alain Joye
  37.  * @license    http://www.opensource.org/licenses/bsd-license.php
  38.  *             BSD License
  39.  * @version    CVS: $Id: Span.php,v 1.9 2006/11/21 17:38:15 firman Exp $
  40.  * @link       http://pear.php.net/package/Date
  41.  * @since      File available since Release 1.4
  42.  */
  43.  
  44. // }}}
  45. // {{{ Includes
  46.  
  47. /**
  48.  * Get the Date class
  49.  */
  50. require_once 'Date.php';
  51.  
  52. /**
  53.  * Get the Date_Calc class
  54.  */
  55. require_once 'Date/Calc.php';
  56.  
  57. // }}}
  58. // {{{ Constants
  59.  
  60. /**
  61.  * Non Numeric Separated Values (NNSV) Input Format.
  62.  *
  63.  * Input format guessed from something like this:
  64.  * days<sep>hours<sep>minutes<sep>seconds
  65.  * Where <sep> is any quantity of non numeric chars. If no values are
  66.  * given, time span is set to zero, if one value is given, it's used for
  67.  * hours, if two values are given it's used for hours and minutes and if
  68.  * three values are given, it's used for hours, minutes and seconds.<br>
  69.  * Examples:<br>
  70.  * ''                   -> 0, 0, 0, 0 (days, hours, minutes, seconds)<br>
  71.  * '12'                 -> 0, 12, 0, 0
  72.  * '12.30'              -> 0, 12, 30, 0<br>
  73.  * '12:30:18'           -> 0, 12, 30, 18<br>
  74.  * '3-12-30-18'         -> 3, 12, 30, 18<br>
  75.  * '3 days, 12-30-18'   -> 3, 12, 30, 18<br>
  76.  * '12:30 with 18 secs' -> 0, 12, 30, 18<br>
  77.  *
  78.  * @const int
  79.  */
  80. define('DATE_SPAN_INPUT_FORMAT_NNSV', 1);
  81.  
  82. // }}}
  83. // {{{ Global Variables
  84.  
  85. /**
  86.  * Default time format when converting to a string.
  87.  *
  88.  * @global string
  89.  */
  90. $GLOBALS['_DATE_SPAN_FORMAT']  = '%C';
  91.  
  92. /**
  93.  * Default time format when converting from a string.
  94.  *
  95.  * @global mixed
  96.  */
  97. $GLOBALS['_DATE_SPAN_INPUT_FORMAT'] = DATE_SPAN_INPUT_FORMAT_NNSV;
  98.  
  99. // }}}
  100. // {{{ Class: Date_Span
  101.  
  102. /**
  103.  * Generic time span handling class for PEAR
  104.  *
  105.  * @author     Leandro Lucarella <llucax@php.net>
  106.  * @author     Pierre-Alain Joye <pajoye@php.net>
  107.  * @copyright  1997-2006 Leandro Lucarella, Pierre-Alain Joye
  108.  * @license    http://www.opensource.org/licenses/bsd-license.php
  109.  *             BSD License
  110.  * @version    Release: 1.4.7
  111.  * @link       http://pear.php.net/package/Date
  112.  * @since      Class available since Release 1.4
  113.  */
  114. class Date_Span
  115. {
  116.     // {{{ Properties
  117.  
  118.     /**
  119.      * @var int
  120.      */
  121.     var $day;
  122.  
  123.     /**
  124.      * @var int
  125.      */
  126.     var $hour;
  127.  
  128.     /**
  129.      * @var int
  130.      */
  131.     var $minute;
  132.  
  133.     /**
  134.      * @var int
  135.      */
  136.     var $second;
  137.  
  138.     // }}}
  139.     // {{{ Constructor
  140.  
  141.     /**
  142.      * Constructor.
  143.      *
  144.      * Creates the time span object calling the set() method.
  145.      *
  146.      * @param  mixed $time   Time span expression.
  147.      * @param  mixed $format Format string to set it from a string or the
  148.      *                       second date set it from a date diff.
  149.      *
  150.      * @see    set()
  151.      * @access public
  152.      */
  153.     function Date_Span($time = 0, $format = null)
  154.     {
  155.         $this->set($time, $format);
  156.     }
  157.  
  158.     // }}}
  159.     // {{{ set()
  160.  
  161.     /**
  162.      * Set the time span to a new value in a 'smart' way.
  163.      *
  164.      * Sets the time span depending on the argument types, calling
  165.      * to the appropriate setFromXxx() method.
  166.      *
  167.      * @param  mixed $time   Time span expression.
  168.      * @param  mixed $format Format string to set it from a string or the
  169.      *                       second date set it from a date diff.
  170.      *
  171.      * @return bool  true on success.
  172.      *
  173.      * @see    setFromObject()
  174.      * @see    setFromArray()
  175.      * @see    setFromString()
  176.      * @see    setFromSeconds()
  177.      * @see    setFromDateDiff()
  178.      * @access public
  179.      */
  180.     function set($time = 0, $format = null)
  181.     {
  182.         if (is_a($time, 'date_span')) {
  183.             return $this->copy($time);
  184.         } elseif (is_a($time, 'date') and is_a($format, 'date')) {
  185.             return $this->setFromDateDiff($time, $format);
  186.         } elseif (is_array($time)) {
  187.             return $this->setFromArray($time);
  188.         } elseif (is_string($time)) {
  189.             return $this->setFromString($time, $format);
  190.         } elseif (is_int($time)) {
  191.             return $this->setFromSeconds($time);
  192.         } else {
  193.             return $this->setFromSeconds(0);
  194.         }
  195.     }
  196.  
  197.     // }}}
  198.     // {{{ setFromArray()
  199.  
  200.     /**
  201.      * Set the time span from an array.
  202.      *
  203.      * Set the time span from an array. Any value can be a float (but it
  204.      * has no sense in seconds), for example array(23.5, 20, 0) is
  205.      * interpreted as 23 hours, .5*60 + 20 = 50 minutes and 0 seconds.
  206.      *
  207.      * @param  array $time Items are counted from right to left. First
  208.      *                     item is for seconds, second for minutes, third
  209.      *                     for hours and fourth for days. If there are
  210.      *                     less items than 4, zero (0) is assumed for the
  211.      *                     absent values.
  212.      *
  213.      * @return bool  True on success.
  214.      *
  215.      * @access public
  216.      */
  217.     function setFromArray($time)
  218.     {
  219.         if (!is_array($time)) {
  220.             return false;
  221.         }
  222.         $tmp1 = new Date_Span;
  223.         if (!$tmp1->setFromSeconds(@array_pop($time))) {
  224.             return false;
  225.         }
  226.         $tmp2 = new Date_Span;
  227.         if (!$tmp2->setFromMinutes(@array_pop($time))) {
  228.             return false;
  229.         }
  230.         $tmp1->add($tmp2);
  231.         if (!$tmp2->setFromHours(@array_pop($time))) {
  232.             return false;
  233.         }
  234.         $tmp1->add($tmp2);
  235.         if (!$tmp2->setFromDays(@array_pop($time))) {
  236.             return false;
  237.         }
  238.         $tmp1->add($tmp2);
  239.         return $this->copy($tmp1);
  240.     }
  241.  
  242.     // }}}
  243.     // {{{ setFromString()
  244.  
  245.     /**
  246.      * Set the time span from a string based on an input format.
  247.      *
  248.      * Set the time span from a string based on an input format. This is
  249.      * some like a mix of format() method and sscanf() PHP function. The
  250.      * error checking and validation of this function is very primitive,
  251.      * so you should be carefull when using it with unknown $time strings.
  252.      * With this method you are assigning day, hour, minute and second
  253.      * values, and the last values are used. This means that if you use
  254.      * something like setFromString('10, 20', '%H, %h') your time span
  255.      * would be 20 hours long. Allways remember that this method set
  256.      * <b>all</b> the values, so if you had a $time span 30 minutes long
  257.      * and you make $time->setFromString('20 hours', '%H hours'), $time
  258.      * span would be 20 hours long (and not 20 hours and 30 minutes).
  259.      * Input format options:<br>
  260.      *  <code>%C</code> Days with time, same as "%D, %H:%M:%S".<br>
  261.      *  <code>%d</code> Total days as a float number
  262.      *                  (2 days, 12 hours = 2.5 days).<br>
  263.      *  <code>%D</code> Days as a decimal number.<br>
  264.      *  <code>%e</code> Total hours as a float number
  265.      *                  (1 day, 2 hours, 30 minutes = 26.5 hours).<br>
  266.      *  <code>%f</code> Total minutes as a float number
  267.      *                  (2 minutes, 30 seconds = 2.5 minutes).<br>
  268.      *  <code>%g</code> Total seconds as a decimal number
  269.      *                  (2 minutes, 30 seconds = 90 seconds).<br>
  270.      *  <code>%h</code> Hours as decimal number.<br>
  271.      *  <code>%H</code> Hours as decimal number limited to 2 digits.<br>
  272.      *  <code>%m</code> Minutes as a decimal number.<br>
  273.      *  <code>%M</code> Minutes as a decimal number limited to 2 digits.<br>
  274.      *  <code>%n</code> Newline character (\n).<br>
  275.      *  <code>%p</code> Either 'am' or 'pm' depending on the time. If 'pm'
  276.      *                  is detected it adds 12 hours to the resulting time
  277.      *                  span (without any checks). This is case
  278.      *                  insensitive.<br>
  279.      *  <code>%r</code> Time in am/pm notation, same as "%H:%M:%S %p".<br>
  280.      *  <code>%R</code> Time in 24-hour notation, same as "%H:%M".<br>
  281.      *  <code>%s</code> Seconds as a decimal number.<br>
  282.      *  <code>%S</code> Seconds as a decimal number limited to 2 digits.<br>
  283.      *  <code>%t</code> Tab character (\t).<br>
  284.      *  <code>%T</code> Current time equivalent, same as "%H:%M:%S".<br>
  285.      *  <code>%%</code> Literal '%'.<br>
  286.      *
  287.      * @param  string $time   String from where to get the time span
  288.      *                        information.
  289.      * @param  string $format Format string.
  290.      *
  291.      * @return bool   True on success.
  292.      *
  293.      * @access public
  294.      */
  295.     function setFromString($time, $format = null)
  296.     {
  297.         if (is_null($format)) {
  298.             $format = $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  299.         }
  300.         // If format is a string, it parses the string format.
  301.         if (is_string($format)) {
  302.             $str = '';
  303.             $vars = array();
  304.             $pm = 'am';
  305.             $day = $hour = $minute = $second = 0;
  306.             for ($i = 0; $i < strlen($format); $i++) {
  307.                 $char = $format{$i};
  308.                 if ($char == '%') {
  309.                     $nextchar = $format{++$i};
  310.                     switch ($nextchar) {
  311.                         case 'c':
  312.                             $str .= '%d, %d:%d:%d';
  313.                             array_push(
  314.                                 $vars, 'day', 'hour', 'minute', 'second');
  315.                             break;
  316.                         case 'C':
  317.                             $str .= '%d, %2d:%2d:%2d';
  318.                             array_push(
  319.                                 $vars, 'day', 'hour', 'minute', 'second');
  320.                             break;
  321.                         case 'd':
  322.                             $str .= '%f';
  323.                             array_push($vars, 'day');
  324.                             break;
  325.                         case 'D':
  326.                             $str .= '%d';
  327.                             array_push($vars, 'day');
  328.                             break;
  329.                         case 'e':
  330.                             $str .= '%f';
  331.                             array_push($vars, 'hour');
  332.                             break;
  333.                         case 'f':
  334.                             $str .= '%f';
  335.                             array_push($vars, 'minute');
  336.                             break;
  337.                         case 'g':
  338.                             $str .= '%f';
  339.                             array_push($vars, 'second');
  340.                             break;
  341.                         case 'h':
  342.                             $str .= '%d';
  343.                             array_push($vars, 'hour');
  344.                             break;
  345.                         case 'H':
  346.                             $str .= '%2d';
  347.                             array_push($vars, 'hour');
  348.                             break;
  349.                         case 'm':
  350.                             $str .= '%d';
  351.                             array_push($vars, 'minute');
  352.                             break;
  353.                         case 'M':
  354.                             $str .= '%2d';
  355.                             array_push($vars, 'minute');
  356.                             break;
  357.                         case 'n':
  358.                             $str .= "\n";
  359.                             break;
  360.                         case 'p':
  361.                             $str .= '%2s';
  362.                             array_push($vars, 'pm');
  363.                             break;
  364.                         case 'r':
  365.                             $str .= '%2d:%2d:%2d %2s';
  366.                             array_push(
  367.                                 $vars, 'hour', 'minute', 'second', 'pm');
  368.                             break;
  369.                         case 'R':
  370.                             $str .= '%2d:%2d';
  371.                             array_push($vars, 'hour', 'minute');
  372.                             break;
  373.                         case 's':
  374.                             $str .= '%d';
  375.                             array_push($vars, 'second');
  376.                             break;
  377.                         case 'S':
  378.                             $str .= '%2d';
  379.                             array_push($vars, 'second');
  380.                             break;
  381.                         case 't':
  382.                             $str .= "\t";
  383.                             break;
  384.                         case 'T':
  385.                             $str .= '%2d:%2d:%2d';
  386.                             array_push($vars, 'hour', 'minute', 'second');
  387.                             break;
  388.                         case '%':
  389.                             $str .= "%";
  390.                             break;
  391.                         default:
  392.                             $str .= $char . $nextchar;
  393.                     }
  394.                 } else {
  395.                     $str .= $char;
  396.                 }
  397.             }
  398.             $vals = sscanf($time, $str);
  399.             foreach ($vals as $i => $val) {
  400.                 if (is_null($val)) {
  401.                     return false;
  402.                 }
  403.                 $$vars[$i] = $val;
  404.             }
  405.             if (strcasecmp($pm, 'pm') == 0) {
  406.                 $hour += 12;
  407.             } elseif (strcasecmp($pm, 'am') != 0) {
  408.                 return false;
  409.             }
  410.             $this->setFromArray(array($day, $hour, $minute, $second));
  411.         // If format is a integer, it uses a predefined format
  412.         // detection method.
  413.         } elseif (is_integer($format)) {
  414.             switch ($format) {
  415.                 case DATE_SPAN_INPUT_FORMAT_NNSV:
  416.                     $time = preg_split('/\D+/', $time);
  417.                     switch (count($time)) {
  418.                         case 0:
  419.                             return $this->setFromArray(
  420.                                 array(0, 0, 0, 0));
  421.                         case 1:
  422.                             return $this->setFromArray(
  423.                                 array(0, $time[0], 0, 0));
  424.                         case 2:
  425.                             return $this->setFromArray(
  426.                                 array(0, $time[0], $time[1], 0));
  427.                         case 3:
  428.                             return $this->setFromArray(
  429.                                 array(0, $time[0], $time[1], $time[2]));
  430.                         default:
  431.                             return $this->setFromArray($time);
  432.                     }
  433.                     break;
  434.             }
  435.         }
  436.         return false;
  437.     }
  438.  
  439.     // }}}
  440.     // {{{ setFromSeconds()
  441.  
  442.     /**
  443.      * Set the time span from a total number of seconds.
  444.      *
  445.      * @param  int  $seconds Total number of seconds.
  446.      *
  447.      * @return bool True on success.
  448.      *
  449.      * @access public
  450.      */
  451.     function setFromSeconds($seconds)
  452.     {
  453.         if ($seconds < 0) {
  454.             return false;
  455.         }
  456.         $sec  = intval($seconds);
  457.         $min  = floor($sec / 60);
  458.         $hour = floor($min / 60);
  459.         $day  = intval(floor($hour / 24));
  460.         $this->second = $sec % 60;
  461.         $this->minute = $min % 60;
  462.         $this->hour   = $hour % 24;
  463.         $this->day    = $day;
  464.         return true;
  465.     }
  466.  
  467.     // }}}
  468.     // {{{ setFromMinutes()
  469.  
  470.     /**
  471.      * Set the time span from a total number of minutes.
  472.      *
  473.      * @param  float $minutes Total number of minutes.
  474.      *
  475.      * @return bool  True on success.
  476.      *
  477.      * @access public
  478.      */
  479.     function setFromMinutes($minutes)
  480.     {
  481.         return $this->setFromSeconds(round($minutes * 60));
  482.     }
  483.  
  484.     // }}}
  485.     // {{{ setFromHours()
  486.  
  487.     /**
  488.      * Set the time span from a total number of hours.
  489.      *
  490.      * @param  float $hours Total number of hours.
  491.      *
  492.      * @return bool  True on success.
  493.      *
  494.      * @access public
  495.      */
  496.     function setFromHours($hours)
  497.     {
  498.         return $this->setFromSeconds(round($hours * 3600));
  499.     }
  500.  
  501.     // }}}
  502.     // {{{ setFromDays()
  503.  
  504.     /**
  505.      * Set the time span from a total number of days.
  506.      *
  507.      * @param  float $days Total number of days.
  508.      *
  509.      * @return bool  True on success.
  510.      *
  511.      * @access public
  512.      */
  513.     function setFromDays($days)
  514.     {
  515.         return $this->setFromSeconds(round($days * 86400));
  516.     }
  517.  
  518.     // }}}
  519.     // {{{ setFromDateDiff()
  520.  
  521.     /**
  522.      * Set the span from the elapsed time between two dates.
  523.      *
  524.      * Set the span from the elapsed time between two dates. The time span
  525.      * is allways positive, so the date's order is not important.
  526.      *
  527.      * @param  object Date $date1 First Date.
  528.      * @param  object Date $date2 Second Date.
  529.      *
  530.      * @return bool  True on success.
  531.      *
  532.      * @access public
  533.      */
  534.     function setFromDateDiff($date1, $date2)
  535.     {
  536.         if (!is_a($date1, 'date') or !is_a($date2, 'date')) {
  537.             return false;
  538.         }
  539.         $date1->toUTC();
  540.         $date2->toUTC();
  541.         if ($date1->after($date2)) {
  542.             list($date1, $date2) = array($date2, $date1);
  543.         }
  544.         $days = Date_Calc::dateDiff(
  545.             $date1->getDay(), $date1->getMonth(), $date1->getYear(),
  546.             $date2->getDay(), $date2->getMonth(), $date2->getYear()
  547.         );
  548.         $hours = $date2->getHour() - $date1->getHour();
  549.         $mins  = $date2->getMinute() - $date1->getMinute();
  550.         $secs  = $date2->getSecond() - $date1->getSecond();
  551.         $this->setFromSeconds(
  552.             $days * 86400 + $hours * 3600 + $mins * 60 + $secs
  553.         );
  554.         return true;
  555.     }
  556.  
  557.     // }}}
  558.     // {{{ copy()
  559.  
  560.     /**
  561.      * Set the time span from another time object.
  562.      *
  563.      * @param  object Date_Span $time Source time span object.
  564.      *
  565.      * @return bool   True on success.
  566.      *
  567.      * @access public
  568.      */
  569.     function copy($time)
  570.     {
  571.         if (is_a($time, 'date_span')) {
  572.             $this->second = $time->second;
  573.             $this->minute = $time->minute;
  574.             $this->hour   = $time->hour;
  575.             $this->day    = $time->day;
  576.             return true;
  577.         } else {
  578.             return false;
  579.         }
  580.     }
  581.  
  582.     // }}}
  583.     // {{{ format()
  584.  
  585.     /**
  586.      * Time span pretty printing (similar to Date::format()).
  587.      *
  588.      * Formats the time span in the given format, similar to
  589.      * strftime() and Date::format().<br>
  590.      * <br>
  591.      * Formatting options:<br>
  592.      *  <code>%C</code> Days with time, same as "%D, %H:%M:%S".<br>
  593.      *  <code>%d</code> Total days as a float number
  594.      *                  (2 days, 12 hours = 2.5 days).<br>
  595.      *  <code>%D</code> Days as a decimal number.<br>
  596.      *  <code>%e</code> Total hours as a float number
  597.      *                  (1 day, 2 hours, 30 minutes = 26.5 hours).<br>
  598.      *  <code>%E</code> Total hours as a decimal number
  599.      *                  (1 day, 2 hours, 40 minutes = 26 hours).<br>
  600.      *  <code>%f</code> Total minutes as a float number
  601.      *                  (2 minutes, 30 seconds = 2.5 minutes).<br>
  602.      *  <code>%F</code> Total minutes as a decimal number
  603.      *                  (1 hour, 2 minutes, 40 seconds = 62 minutes).<br>
  604.      *  <code>%g</code> Total seconds as a decimal number
  605.      *                  (2 minutes, 30 seconds = 90 seconds).<br>
  606.      *  <code>%h</code> Hours as decimal number (0 to 23).<br>
  607.      *  <code>%H</code> Hours as decimal number (00 to 23).<br>
  608.      *  <code>%i</code> Hours as decimal number on 12-hour clock
  609.      *                  (1 to 12).<br>
  610.      *  <code>%I</code> Hours as decimal number on 12-hour clock
  611.      *                  (01 to 12).<br>
  612.      *  <code>%m</code> Minutes as a decimal number (0 to 59).<br>
  613.      *  <code>%M</code> Minutes as a decimal number (00 to 59).<br>
  614.      *  <code>%n</code> Newline character (\n).<br>
  615.      *  <code>%p</code> Either 'am' or 'pm' depending on the time.<br>
  616.      *  <code>%P</code> Either 'AM' or 'PM' depending on the time.<br>
  617.      *  <code>%r</code> Time in am/pm notation, same as "%I:%M:%S %p".<br>
  618.      *  <code>%R</code> Time in 24-hour notation, same as "%H:%M".<br>
  619.      *  <code>%s</code> Seconds as a decimal number (0 to 59).<br>
  620.      *  <code>%S</code> Seconds as a decimal number (00 to 59).<br>
  621.      *  <code>%t</code> Tab character (\t).<br>
  622.      *  <code>%T</code> Current time equivalent, same as "%H:%M:%S".<br>
  623.      *  <code>%%</code> Literal '%'.<br>
  624.      *
  625.      * @param  string $format The format string for returned time span.
  626.      *
  627.      * @return string The time span in specified format.
  628.      *
  629.      * @access public
  630.      */
  631.     function format($format = null)
  632.     {
  633.         if (is_null($format)) {
  634.             $format = $GLOBALS['_DATE_SPAN_FORMAT'];
  635.         }
  636.         $output = '';
  637.         for ($i = 0; $i < strlen($format); $i++) {
  638.             $char = $format{$i};
  639.             if ($char == '%') {
  640.                 $nextchar = $format{++$i};
  641.                 switch ($nextchar) {
  642.                     case 'C':
  643.                         $output .= sprintf(
  644.                             '%d, %02d:%02d:%02d',
  645.                             $this->day,
  646.                             $this->hour,
  647.                             $this->minute,
  648.                             $this->second
  649.                         );
  650.                         break;
  651.                     case 'd':
  652.                         $output .= $this->toDays();
  653.                         break;
  654.                     case 'D':
  655.                         $output .= $this->day;
  656.                         break;
  657.                     case 'e':
  658.                         $output .= $this->toHours();
  659.                         break;
  660.                     case 'E':
  661.                         $output .= floor($this->toHours());
  662.                         break;
  663.                     case 'f':
  664.                         $output .= $this->toMinutes();
  665.                         break;
  666.                     case 'F':
  667.                         $output .= floor($this->toMinutes());
  668.                         break;
  669.                     case 'g':
  670.                         $output .= $this->toSeconds();
  671.                         break;
  672.                     case 'h':
  673.                         $output .= $this->hour;
  674.                         break;
  675.                     case 'H':
  676.                         $output .= sprintf('%02d', $this->hour);
  677.                         break;
  678.                     case 'i':
  679.                         $hour =
  680.                             ($this->hour + 1) > 12 ?
  681.                             $this->hour - 12 :
  682.                             $this->hour;
  683.                         $output .= ($hour == 0) ? 12 : $hour;
  684.                         break;
  685.                     case 'I':
  686.                         $hour =
  687.                             ($this->hour + 1) > 12 ?
  688.                             $this->hour - 12 :
  689.                             $this->hour;
  690.                         $output .= sprintf('%02d', $hour==0 ? 12 : $hour);
  691.                         break;
  692.                     case 'm':
  693.                         $output .= $this->minute;
  694.                         break;
  695.                     case 'M':
  696.                         $output .= sprintf('%02d',$this->minute);
  697.                         break;
  698.                     case 'n':
  699.                         $output .= "\n";
  700.                         break;
  701.                     case 'p':
  702.                         $output .= $this->hour >= 12 ? 'pm' : 'am';
  703.                         break;
  704.                     case 'P':
  705.                         $output .= $this->hour >= 12 ? 'PM' : 'AM';
  706.                         break;
  707.                     case 'r':
  708.                         $hour =
  709.                             ($this->hour + 1) > 12 ?
  710.                             $this->hour - 12 :
  711.                             $this->hour;
  712.                         $output .= sprintf(
  713.                             '%02d:%02d:%02d %s',
  714.                             $hour==0 ?  12 : $hour,
  715.                             $this->minute,
  716.                             $this->second,
  717.                             $this->hour >= 12 ? 'pm' : 'am'
  718.                         );
  719.                         break;
  720.                     case 'R':
  721.                         $output .= sprintf(
  722.                             '%02d:%02d', $this->hour, $this->minute
  723.                         );
  724.                         break;
  725.                     case 's':
  726.                         $output .= $this->second;
  727.                         break;
  728.                     case 'S':
  729.                         $output .= sprintf('%02d', $this->second);
  730.                         break;
  731.                     case 't':
  732.                         $output .= "\t";
  733.                         break;
  734.                     case 'T':
  735.                         $output .= sprintf(
  736.                             '%02d:%02d:%02d',
  737.                             $this->hour, $this->minute, $this->second
  738.                         );
  739.                         break;
  740.                     case '%':
  741.                         $output .= "%";
  742.                         break;
  743.                     default:
  744.                         $output .= $char . $nextchar;
  745.                 }
  746.             } else {
  747.                 $output .= $char;
  748.             }
  749.         }
  750.         return $output;
  751.     }
  752.  
  753.     // }}}
  754.     // {{{ toSeconds()
  755.  
  756.     /**
  757.      * Convert time span to seconds.
  758.      *
  759.      * @return int Time span as an integer number of seconds.
  760.      *
  761.      * @access public
  762.      */
  763.     function toSeconds()
  764.     {
  765.         return $this->day * 86400 + $this->hour * 3600 +
  766.             $this->minute * 60 + $this->second;
  767.     }
  768.  
  769.     // }}}
  770.     // {{{ toMinutes()
  771.  
  772.     /**
  773.      * Convert time span to minutes.
  774.      *
  775.      * @return float Time span as a decimal number of minutes.
  776.      *
  777.      * @access public
  778.      */
  779.     function toMinutes()
  780.     {
  781.         return $this->day * 1440 + $this->hour * 60 + $this->minute +
  782.             $this->second / 60;
  783.     }
  784.  
  785.     // }}}
  786.     // {{{ toHours()
  787.  
  788.     /**
  789.      * Convert time span to hours.
  790.      *
  791.      * @return float Time span as a decimal number of hours.
  792.      *
  793.      * @access public
  794.      */
  795.     function toHours()
  796.     {
  797.         return $this->day * 24 + $this->hour + $this->minute / 60 +
  798.             $this->second / 3600;
  799.     }
  800.  
  801.     // }}}
  802.     // {{{ toDays()
  803.  
  804.     /**
  805.      * Convert time span to days.
  806.      *
  807.      * @return float Time span as a decimal number of days.
  808.      *
  809.      * @access public
  810.      */
  811.     function toDays()
  812.     {
  813.         return $this->day + $this->hour / 24 + $this->minute / 1440 +
  814.             $this->second / 86400;
  815.     }
  816.  
  817.     // }}}
  818.     // {{{ add()
  819.  
  820.     /**
  821.      * Adds a time span.
  822.      *
  823.      * @param  object Date_Span $time Time span to add.
  824.      *
  825.      * @access public
  826.      */
  827.     function add($time)
  828.     {
  829.         return $this->setFromSeconds(
  830.             $this->toSeconds() + $time->toSeconds()
  831.         );
  832.     }
  833.  
  834.     // }}}
  835.     // {{{ substract()
  836.  
  837.     /**
  838.      * Subtracts a time span.
  839.      *
  840.      * Subtracts a time span. If the time span to subtract is larger
  841.      * than the original, the result is zero (there's no sense in
  842.      * negative time spans).
  843.      *
  844.      * @param  object Date_Span $time Time span to subtract.
  845.      *
  846.      * @access public
  847.      */
  848.     function subtract($time)
  849.     {
  850.         $sub = $this->toSeconds() - $time->toSeconds();
  851.         if ($sub < 0) {
  852.             $this->setFromSeconds(0);
  853.         } else {
  854.             $this->setFromSeconds($sub);
  855.         }
  856.     }
  857.  
  858.     // }}}
  859.     // {{{ equal()
  860.  
  861.     /**
  862.      * Tells if time span is equal to $time.
  863.      *
  864.      * @param  object Date_Span $time Time span to compare to.
  865.      *
  866.      * @return bool   True if the time spans are equal.
  867.      *
  868.      * @access public
  869.      */
  870.     function equal($time)
  871.     {
  872.         return $this->toSeconds() == $time->toSeconds();
  873.     }
  874.  
  875.     // }}}
  876.     // {{{ greaterEqual()
  877.  
  878.     /**
  879.      * Tells if this time span is greater or equal than $time.
  880.      *
  881.      * @param  object Date_Span $time Time span to compare to.
  882.      *
  883.      * @return bool   True if this time span is greater or equal than $time.
  884.      *
  885.      * @access public
  886.      */
  887.     function greaterEqual($time)
  888.     {
  889.         return $this->toSeconds() >= $time->toSeconds();
  890.     }
  891.  
  892.     // }}}
  893.     // {{{ lowerEqual()
  894.  
  895.     /**
  896.      * Tells if this time span is lower or equal than $time.
  897.      *
  898.      * @param  object Date_Span $time Time span to compare to.
  899.      *
  900.      * @return bool   True if this time span is lower or equal than $time.
  901.      *
  902.      * @access public
  903.      */
  904.     function lowerEqual($time)
  905.     {
  906.         return $this->toSeconds() <= $time->toSeconds();
  907.     }
  908.  
  909.     // }}}
  910.     // {{{ greater()
  911.  
  912.     /**
  913.      * Tells if this time span is greater than $time.
  914.      *
  915.      * @param  object Date_Span $time Time span to compare to.
  916.      *
  917.      * @return bool   True if this time span is greater than $time.
  918.      *
  919.      * @access public
  920.      */
  921.     function greater($time)
  922.     {
  923.         return $this->toSeconds() > $time->toSeconds();
  924.     }
  925.  
  926.     // }}}
  927.     // {{{ lower()
  928.  
  929.     /**
  930.      * Tells if this time span is lower than $time.
  931.      *
  932.      * @param  object Date_Span $time Time span to compare to.
  933.      *
  934.      * @return bool   True if this time span is lower than $time.
  935.      *
  936.      * @access public
  937.      */
  938.     function lower($time)
  939.     {
  940.         return $this->toSeconds() < $time->toSeconds();
  941.     }
  942.  
  943.     // }}}
  944.     // {{{ compare()
  945.  
  946.     /**
  947.      * Compares two time spans.
  948.      *
  949.      * Compares two time spans. Suitable for use in sorting functions.
  950.      *
  951.      * @param  object Date_Span $time1 The first time span.
  952.      * @param  object Date_Span $time2 The second time span.
  953.      *
  954.      * @return int    0 if the time spans are equal, -1 if time1 is lower
  955.      *                than time2, 1 if time1 is greater than time2.
  956.      *
  957.      * @static
  958.      * @access public
  959.      */
  960.     function compare($time1, $time2)
  961.     {
  962.         if ($time1->equal($time2)) {
  963.             return 0;
  964.         } elseif ($time1->lower($time2)) {
  965.             return -1;
  966.         } else {
  967.             return 1;
  968.         }
  969.     }
  970.  
  971.     // }}}
  972.     // {{{ isEmpty()
  973.  
  974.     /**
  975.      * Tells if the time span is empty (zero length).
  976.      *
  977.      * @return bool True is it's empty.
  978.      */
  979.     function isEmpty()
  980.     {
  981.         return !$this->day && !$this->hour && !$this->minute && !$this->second;
  982.     }
  983.  
  984.     // }}}
  985.     // {{{ setDefaultInputFormat()
  986.  
  987.     /**
  988.      * Set the default input format.
  989.      *
  990.      * @param  mixed $format New default input format.
  991.      *
  992.      * @return mixed Previous default input format.
  993.      *
  994.      * @static
  995.      */
  996.     function setDefaultInputFormat($format)
  997.     {
  998.         $old = $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  999.         $GLOBALS['_DATE_SPAN_INPUT_FORMAT'] = $format;
  1000.         return $old;
  1001.     }
  1002.  
  1003.     // }}}
  1004.     // {{{ getDefaultInputFormat()
  1005.  
  1006.     /**
  1007.      * Get the default input format.
  1008.      *
  1009.      * @return mixed Default input format.
  1010.      *
  1011.      * @static
  1012.      */
  1013.     function getDefaultInputFormat()
  1014.     {
  1015.         return $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  1016.     }
  1017.  
  1018.     // }}}
  1019.     // {{{ setDefaultFormat()
  1020.  
  1021.     /**
  1022.      * Set the default format.
  1023.      *
  1024.      * @param  mixed $format New default format.
  1025.      *
  1026.      * @return mixed Previous default format.
  1027.      *
  1028.      * @static
  1029.      */
  1030.     function setDefaultFormat($format)
  1031.     {
  1032.         $old = $GLOBALS['_DATE_SPAN_FORMAT'];
  1033.         $GLOBALS['_DATE_SPAN_FORMAT'] = $format;
  1034.         return $old;
  1035.     }
  1036.  
  1037.     // }}}
  1038.     // {{{ getDefaultFormat()
  1039.  
  1040.     /**
  1041.      * Get the default format.
  1042.      *
  1043.      * @return mixed Default format.
  1044.      *
  1045.      * @static
  1046.      */
  1047.     function getDefaultFormat()
  1048.     {
  1049.         return $GLOBALS['_DATE_SPAN_FORMAT'];
  1050.     }
  1051.  
  1052.     // }}}
  1053.     // {{{ __clone()
  1054.  
  1055.     /**
  1056.      * Returns a copy of the object (workarround for PHP5 forward compatibility).
  1057.      *
  1058.      * @return object Date_Span Copy of the object.
  1059.      */
  1060.     function __clone() {
  1061.         $c = get_class($this);
  1062.         $s = new $c;
  1063.         $s->day    = $this->day;
  1064.         $s->hour   = $this->hour;
  1065.         $s->minute = $this->minute;
  1066.         $s->second = $this->second;
  1067.         return $s;
  1068.     }
  1069.  
  1070.     // }}}
  1071. }
  1072.  
  1073. // }}}
  1074.  
  1075. /*
  1076.  * Local variables:
  1077.  * mode: php
  1078.  * tab-width: 4
  1079.  * c-basic-offset: 4
  1080.  * c-hanging-comment-ender-p: nil
  1081.  * End:
  1082.  */
  1083. ?>