Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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
?>