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