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 date handling class for PEAR
8
 *
9
 * Generic date handling class for PEAR.  Attempts to be time zone aware
10
 * through the Date::TimeZone class.  Supports several operations from
11
 * Date::Calc on Date objects.
12
 *
13
 * PHP versions 4 and 5
14
 *
15
 * LICENSE:
16
 *
17
 * Copyright (c) 1997-2006 Baba Buehler, Pierre-Alain Joye
18
 * All rights reserved.
19
 *
20
 * Redistribution and use in source and binary forms, with or without
21
 * modification, are permitted under the terms of the BSD License.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category   Date and Time
37
 * @package    Date
38
 * @author     Baba Buehler <baba@babaz.com>
39
 * @author     Pierre-Alain Joye <pajoye@php.net>
40
 * @author     Firman Wandayandi <firman@php.net>
41
 * @copyright  1997-2006 Baba Buehler, Pierre-Alain Joye
42
 * @license    http://www.opensource.org/licenses/bsd-license.php
43
 *             BSD License
44
 * @version    CVS: $Id: Date.php,v 1.41 2006/11/22 00:28:03 firman Exp $
45
 * @link       http://pear.php.net/package/Date
46
 */
47
 
48
// }}}
49
 
50
// {{{ Includes
51
 
52
/**
53
 * Load Date_TimeZone.
54
 */
55
require_once 'Date/TimeZone.php';
56
 
57
/**
58
 * Load Date_Calc.
59
 */
60
require_once 'Date/Calc.php';
61
 
62
/**
63
 * Load Date_Span.
64
 */
65
require_once 'Date/Span.php';
66
 
67
// }}}
68
// {{{ Constants
69
 
70
// {{{ Output formats Pass this to getDate().
71
 
72
/**
73
 * "YYYY-MM-DD HH:MM:SS"
74
 */
75
define('DATE_FORMAT_ISO', 1);
76
 
77
/**
78
 * "YYYYMMSSTHHMMSS(Z|(+/-)HHMM)?"
79
 */
80
define('DATE_FORMAT_ISO_BASIC', 2);
81
 
82
/**
83
 * "YYYY-MM-SSTHH:MM:SS(Z|(+/-)HH:MM)?"
84
 */
85
define('DATE_FORMAT_ISO_EXTENDED', 3);
86
 
87
/**
88
 * "YYYY-MM-SSTHH:MM:SS(.S*)?(Z|(+/-)HH:MM)?"
89
 */
90
define('DATE_FORMAT_ISO_EXTENDED_MICROTIME', 6);
91
 
92
/**
93
 * "YYYYMMDDHHMMSS"
94
 */
95
define('DATE_FORMAT_TIMESTAMP', 4);
96
 
97
/**
98
 * long int, seconds since the unix epoch
99
 */
100
define('DATE_FORMAT_UNIXTIME', 5);
101
 
102
// }}}
103
 
104
// }}}
105
// {{{ Class: Date
106
 
107
/**
108
 * Generic date handling class for PEAR
109
 *
110
 * Generic date handling class for PEAR.  Attempts to be time zone aware
111
 * through the Date::TimeZone class.  Supports several operations from
112
 * Date::Calc on Date objects.
113
 *
114
 * @author     Baba Buehler <baba@babaz.com>
115
 * @author     Pierre-Alain Joye <pajoye@php.net>
116
 * @author     Firman Wandayandi <firman@php.net>
117
 * @copyright  1997-2006 Baba Buehler, Pierre-Alain Joye
118
 * @license    http://www.opensource.org/licenses/bsd-license.php
119
 *             BSD License
120
 * @version    Release: 1.4.7
121
 * @link       http://pear.php.net/package/Date
122
 */
123
class Date
124
{
125
    // {{{ Properties
126
 
127
    /**
128
     * the year
129
     * @var int
130
     */
131
    var $year;
132
 
133
    /**
134
     * the month
135
     * @var int
136
     */
137
    var $month;
138
 
139
    /**
140
     * the day
141
     * @var int
142
     */
143
    var $day;
144
 
145
    /**
146
     * the hour
147
     * @var int
148
     */
149
    var $hour;
150
 
151
    /**
152
     * the minute
153
     * @var int
154
     */
155
    var $minute;
156
 
157
    /**
158
     * the second
159
     * @var int
160
     */
161
    var $second;
162
 
163
    /**
164
     * the parts of a second
165
     * @var float
166
     */
167
    var $partsecond;
168
 
169
    /**
170
     * timezone for this date
171
     * @var object Date_TimeZone
172
     */
173
    var $tz;
174
 
175
    /**
176
     * define the default weekday abbreviation length
177
     * used by ::format()
178
     * @var int
179
     */
180
    var $getWeekdayAbbrnameLength = 3;
181
 
182
    // }}}
183
    // {{{ Constructor
184
 
185
    /**
186
     * Constructor
187
     *
188
     * Creates a new Date Object initialized to the current date/time in the
189
     * system-default timezone by default.  A date optionally
190
     * passed in may be in the ISO 8601, TIMESTAMP or UNIXTIME format,
191
     * or another Date object.  If no date is passed, the current date/time
192
     * is used.
193
     *
194
     * @access public
195
     * @see setDate()
196
     * @param mixed $date optional - date/time to initialize
197
     * @return object Date the new Date object
198
     */
199
    function Date($date = null)
200
    {
201
        $this->tz = Date_TimeZone::getDefault();
202
        if (is_null($date)) {
203
            $this->setDate(date("Y-m-d H:i:s"));
204
        } elseif (is_a($date, 'Date')) {
205
            $this->copy($date);
206
        } else {
207
            $this->setDate($date);
208
        }
209
    }
210
 
211
    // }}}
212
    // {{{ setDate()
213
 
214
    /**
215
     * Set the fields of a Date object based on the input date and format
216
     *
217
     * Set the fields of a Date object based on the input date and format,
218
     * which is specified by the DATE_FORMAT_* constants.
219
     *
220
     * @access public
221
     * @param string $date input date
222
     * @param int $format Optional format constant (DATE_FORMAT_*) of the input date.
223
     *                    This parameter isn't really needed anymore, but you could
224
     *                    use it to force DATE_FORMAT_UNIXTIME.
225
     */
226
    function setDate($date, $format = DATE_FORMAT_ISO)
227
    {
228
        if (
229
            preg_match('/^(\d{4})-?(\d{2})-?(\d{2})([T\s]?(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?(Z|[\+\-]\d{2}:?\d{2})?)?$/i', $date, $regs)
230
            && $format != DATE_FORMAT_UNIXTIME) {
231
            // DATE_FORMAT_ISO, ISO_BASIC, ISO_EXTENDED, and TIMESTAMP
232
            // These formats are extremely close to each other.  This regex
233
            // is very loose and accepts almost any butchered format you could
234
            // throw at it.  e.g. 2003-10-07 19:45:15 and 2003-10071945:15
235
            // are the same thing in the eyes of this regex, even though the
236
            // latter is not a valid ISO 8601 date.
237
            $this->year       = $regs[1];
238
            $this->month      = $regs[2];
239
            $this->day        = $regs[3];
240
            $this->hour       = isset($regs[5])?$regs[5]:0;
241
            $this->minute     = isset($regs[6])?$regs[6]:0;
242
            $this->second     = isset($regs[7])?$regs[7]:0;
243
            $this->partsecond = isset($regs[8])?(float)$regs[8]:(float)0;
244
 
245
            // if an offset is defined, convert time to UTC
246
            // Date currently can't set a timezone only by offset,
247
            // so it has to store it as UTC
248
            if (isset($regs[9])) {
249
                $this->toUTCbyOffset($regs[9]);
250
            }
251
        } elseif (is_numeric($date)) {
252
            // UNIXTIME
253
            $this->setDate(date("Y-m-d H:i:s", $date));
254
        } else {
255
            // unknown format
256
            $this->year       = 0;
257
            $this->month      = 1;
258
            $this->day        = 1;
259
            $this->hour       = 0;
260
            $this->minute     = 0;
261
            $this->second     = 0;
262
            $this->partsecond = (float)0;
263
        }
264
    }
265
 
266
    // }}}
267
    // {{{ getDate()
268
 
269
    /**
270
     * Get a string (or other) representation of this date
271
     *
272
     * Get a string (or other) representation of this date in the
273
     * format specified by the DATE_FORMAT_* constants.
274
     *
275
     * @access public
276
     * @param int $format format constant (DATE_FORMAT_*) of the output date
277
     * @return string the date in the requested format
278
     */
279
    function getDate($format = DATE_FORMAT_ISO)
280
    {
281
        switch ($format) {
282
        case DATE_FORMAT_ISO:
283
            return $this->format("%Y-%m-%d %T");
284
            break;
285
        case DATE_FORMAT_ISO_BASIC:
286
            $format = "%Y%m%dT%H%M%S";
287
            if ($this->tz->getID() == 'UTC') {
288
                $format .= "Z";
289
            }
290
            return $this->format($format);
291
            break;
292
        case DATE_FORMAT_ISO_EXTENDED:
293
            $format = "%Y-%m-%dT%H:%M:%S";
294
            if ($this->tz->getID() == 'UTC') {
295
                $format .= "Z";
296
            }
297
            return $this->format($format);
298
            break;
299
        case DATE_FORMAT_ISO_EXTENDED_MICROTIME:
300
            $format = "%Y-%m-%dT%H:%M:%s";
301
            if ($this->tz->getID() == 'UTC') {
302
                $format .= "Z";
303
            }
304
            return $this->format($format);
305
            break;
306
        case DATE_FORMAT_TIMESTAMP:
307
            return $this->format("%Y%m%d%H%M%S");
308
            break;
309
        case DATE_FORMAT_UNIXTIME:
310
            return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
311
            break;
312
        }
313
    }
314
 
315
    // }}}
316
    // {{{ copy()
317
 
318
    /**
319
     * Copy values from another Date object
320
     *
321
     * Makes this Date a copy of another Date object.
322
     *
323
     * @access public
324
     * @param object Date $date Date to copy from
325
     */
326
    function copy($date)
327
    {
328
        $this->year = $date->year;
329
        $this->month = $date->month;
330
        $this->day = $date->day;
331
        $this->hour = $date->hour;
332
        $this->minute = $date->minute;
333
        $this->second = $date->second;
334
        $this->tz = $date->tz;
335
    }
336
 
337
    // }}}
338
    // {{{ format()
339
 
340
    /**
341
     *  Date pretty printing, similar to strftime()
342
     *
343
     *  Formats the date in the given format, much like
344
     *  strftime().  Most strftime() options are supported.<br><br>
345
     *
346
     *  formatting options:<br><br>
347
     *
348
     *  <code>%a  </code>  abbreviated weekday name (Sun, Mon, Tue) <br>
349
     *  <code>%A  </code>  full weekday name (Sunday, Monday, Tuesday) <br>
350
     *  <code>%b  </code>  abbreviated month name (Jan, Feb, Mar) <br>
351
     *  <code>%B  </code>  full month name (January, February, March) <br>
352
     *  <code>%C  </code>  century number (the year divided by 100 and truncated to an integer, range 00 to 99) <br>
353
     *  <code>%d  </code>  day of month (range 00 to 31) <br>
354
     *  <code>%D  </code>  same as "%m/%d/%y" <br>
355
     *  <code>%e  </code>  day of month, single digit (range 0 to 31) <br>
356
     *  <code>%E  </code>  number of days since unspecified epoch (integer, Date_Calc::dateToDays()) <br>
357
     *  <code>%H  </code>  hour as decimal number (00 to 23) <br>
358
     *  <code>%I  </code>  hour as decimal number on 12-hour clock (01 to 12) <br>
359
     *  <code>%j  </code>  day of year (range 001 to 366) <br>
360
     *  <code>%m  </code>  month as decimal number (range 01 to 12) <br>
361
     *  <code>%M  </code>  minute as a decimal number (00 to 59) <br>
362
     *  <code>%n  </code>  newline character (\n) <br>
363
     *  <code>%O  </code>  dst-corrected timezone offset expressed as "+/-HH:MM" <br>
364
     *  <code>%o  </code>  raw timezone offset expressed as "+/-HH:MM" <br>
365
     *  <code>%p  </code>  either 'am' or 'pm' depending on the time <br>
366
     *  <code>%P  </code>  either 'AM' or 'PM' depending on the time <br>
367
     *  <code>%r  </code>  time in am/pm notation, same as "%I:%M:%S %p" <br>
368
     *  <code>%R  </code>  time in 24-hour notation, same as "%H:%M" <br>
369
     *  <code>%s  </code>  seconds including the decimal representation smaller than one second <br>
370
     *  <code>%S  </code>  seconds as a decimal number (00 to 59) <br>
371
     *  <code>%t  </code>  tab character (\t) <br>
372
     *  <code>%T  </code>  current time, same as "%H:%M:%S" <br>
373
     *  <code>%w  </code>  weekday as decimal (0 = Sunday) <br>
374
     *  <code>%U  </code>  week number of current year, first sunday as first week <br>
375
     *  <code>%y  </code>  year as decimal (range 00 to 99) <br>
376
     *  <code>%Y  </code>  year as decimal including century (range 0000 to 9999) <br>
377
     *  <code>%%  </code>  literal '%' <br>
378
     * <br>
379
     *
380
     * @access public
381
     * @param string format the format string for returned date/time
382
     * @return string date/time in given format
383
     */
384
    function format($format)
385
    {
386
        $output = "";
387
 
388
        for($strpos = 0; $strpos < strlen($format); $strpos++) {
389
            $char = substr($format,$strpos,1);
390
            if ($char == "%") {
391
                $nextchar = substr($format,$strpos + 1,1);
392
                switch ($nextchar) {
393
                case "a":
394
                    $output .= Date_Calc::getWeekdayAbbrname($this->day,$this->month,$this->year, $this->getWeekdayAbbrnameLength);
395
                    break;
396
                case "A":
397
                    $output .= Date_Calc::getWeekdayFullname($this->day,$this->month,$this->year);
398
                    break;
399
                case "b":
400
                    $output .= Date_Calc::getMonthAbbrname($this->month);
401
                    break;
402
                case "B":
403
                    $output .= Date_Calc::getMonthFullname($this->month);
404
                    break;
405
                case "C":
406
                    $output .= sprintf("%02d",intval($this->year/100));
407
                    break;
408
                case "d":
409
                    $output .= sprintf("%02d",$this->day);
410
                    break;
411
                case "D":
412
                    $output .= sprintf("%02d/%02d/%02d",$this->month,$this->day,$this->year);
413
                    break;
414
                case "e":
415
                    $output .= $this->day * 1; // get rid of leading zero
416
                    break;
417
                case "E":
418
                    $output .= Date_Calc::dateToDays($this->day,$this->month,$this->year);
419
                    break;
420
                case "H":
421
                    $output .= sprintf("%02d", $this->hour);
422
                    break;
423
                case 'h':
424
                    $output .= sprintf("%d", $this->hour);
425
                    break;
426
                case "I":
427
                    $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
428
                    $output .= sprintf("%02d", $hour==0 ? 12 : $hour);
429
                    break;
430
                case "i":
431
                    $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
432
                    $output .= sprintf("%d", $hour==0 ? 12 : $hour);
433
                    break;
434
                case "j":
435
                    $output .= Date_Calc::julianDate($this->day,$this->month,$this->year);
436
                    break;
437
                case "m":
438
                    $output .= sprintf("%02d",$this->month);
439
                    break;
440
                case "M":
441
                    $output .= sprintf("%02d",$this->minute);
442
                    break;
443
                case "n":
444
                    $output .= "\n";
445
                    break;
446
                case "O":
447
                    $offms = $this->tz->getOffset($this);
448
                    $direction = $offms >= 0 ? "+" : "-";
449
                    $offmins = abs($offms) / 1000 / 60;
450
                    $hours = $offmins / 60;
451
                    $minutes = $offmins % 60;
452
                    $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
453
                    break;
454
                case "o":
455
                    $offms = $this->tz->getRawOffset($this);
456
                    $direction = $offms >= 0 ? "+" : "-";
457
                    $offmins = abs($offms) / 1000 / 60;
458
                    $hours = $offmins / 60;
459
                    $minutes = $offmins % 60;
460
                    $output .= sprintf("%s%02d:%02d", $direction, $hours, $minutes);
461
                    break;
462
                case "p":
463
                    $output .= $this->hour >= 12 ? "pm" : "am";
464
                    break;
465
                case "P":
466
                    $output .= $this->hour >= 12 ? "PM" : "AM";
467
                    break;
468
                case "r":
469
                    $hour = ($this->hour + 1) > 12 ? $this->hour - 12 : $this->hour;
470
                    $output .= sprintf("%02d:%02d:%02d %s", $hour==0 ?  12 : $hour, $this->minute, $this->second, $this->hour >= 12 ? "PM" : "AM");
471
                    break;
472
                case "R":
473
                    $output .= sprintf("%02d:%02d", $this->hour, $this->minute);
474
                    break;
475
                case "s":
476
                    $output .= str_replace(',', '.', sprintf("%09f", (float)((float)$this->second + $this->partsecond)));
477
                    break;
478
                case "S":
479
                    $output .= sprintf("%02d", $this->second);
480
                    break;
481
                case "t":
482
                    $output .= "\t";
483
                    break;
484
                case "T":
485
                    $output .= sprintf("%02d:%02d:%02d", $this->hour, $this->minute, $this->second);
486
                    break;
487
                case "w":
488
                    $output .= Date_Calc::dayOfWeek($this->day,$this->month,$this->year);
489
                    break;
490
                case "U":
491
                    $output .= Date_Calc::weekOfYear($this->day,$this->month,$this->year);
492
                    break;
493
                case "y":
494
                    $output .= substr($this->year,2,2);
495
                    break;
496
                case "Y":
497
                    $output .= $this->year;
498
                    break;
499
                case "Z":
500
                    $output .= $this->tz->inDaylightTime($this) ? $this->tz->getDSTShortName() : $this->tz->getShortName();
501
                    break;
502
                case "%":
503
                    $output .= "%";
504
                    break;
505
                default:
506
                    $output .= $char.$nextchar;
507
                }
508
                $strpos++;
509
            } else {
510
                $output .= $char;
511
            }
512
        }
513
        return $output;
514
 
515
    }
516
 
517
    // }}}
518
    // {{{ getTime()
519
 
520
    /**
521
     * Get this date/time in Unix time() format
522
     *
523
     * Get a representation of this date in Unix time() format.  This may only be
524
     * valid for dates from 1970 to ~2038.
525
     *
526
     * @access public
527
     * @return int number of seconds since the unix epoch
528
     */
529
    function getTime()
530
    {
531
        return $this->getDate(DATE_FORMAT_UNIXTIME);
532
    }
533
 
534
    // }}}
535
    // {{{ setTZ()
536
 
537
    /**
538
     * Sets the time zone of this Date
539
     *
540
     * Sets the time zone of this date with the given
541
     * Date_TimeZone object.  Does not alter the date/time,
542
     * only assigns a new time zone.  For conversion, use
543
     * convertTZ().
544
     *
545
     * @access public
546
     * @param object Date_TimeZone $tz the Date_TimeZone object to use, if called
547
     * with a paramater that is not a Date_TimeZone object, will fall through to
548
     * setTZbyID().
549
     */
550
    function setTZ($tz)
551
    {
552
        if(is_a($tz, 'Date_Timezone')) {
553
            $this->tz = $tz;
554
        } else {
555
            $this->setTZbyID($tz);
556
        }
557
    }
558
 
559
    // }}}
560
    // {{{ setTZbyID()
561
 
562
    /**
563
     * Sets the time zone of this date with the given time zone id
564
     *
565
     * Sets the time zone of this date with the given
566
     * time zone id, or to the system default if the
567
     * given id is invalid. Does not alter the date/time,
568
     * only assigns a new time zone.  For conversion, use
569
     * convertTZ().
570
     *
571
     * @access public
572
     * @param string id a time zone id
573
     */
574
    function setTZbyID($id)
575
    {
576
        if (Date_TimeZone::isValidID($id)) {
577
            $this->tz = new Date_TimeZone($id);
578
        } else {
579
            $this->tz = Date_TimeZone::getDefault();
580
        }
581
    }
582
 
583
    // }}}
584
    // {{{ inDaylightTime()
585
 
586
    /**
587
     * Tests if this date/time is in DST
588
     *
589
     * Returns true if daylight savings time is in effect for
590
     * this date in this date's time zone.  See Date_TimeZone::inDaylightTime()
591
     * for compatability information.
592
     *
593
     * @access public
594
     * @return boolean true if DST is in effect for this date
595
     */
596
    function inDaylightTime()
597
    {
598
        return $this->tz->inDaylightTime($this);
599
    }
600
 
601
    // }}}
602
    // {{{ toUTC()
603
 
604
    /**
605
     * Converts this date to UTC and sets this date's timezone to UTC
606
     *
607
     * Converts this date to UTC and sets this date's timezone to UTC
608
     *
609
     * @access public
610
     */
611
    function toUTC()
612
    {
613
        if ($this->tz->getOffset($this) > 0) {
614
            $this->subtractSeconds(intval($this->tz->getOffset($this) / 1000));
615
        } else {
616
            $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
617
        }
618
        $this->tz = new Date_TimeZone('UTC');
619
    }
620
 
621
    // }}}
622
    // {{{ convertTZ()
623
 
624
    /**
625
     * Converts this date to a new time zone
626
     *
627
     * Converts this date to a new time zone.
628
     * WARNING: This may not work correctly if your system does not allow
629
     * putenv() or if localtime() does not work in your environment.  See
630
     * Date::TimeZone::inDaylightTime() for more information.
631
     *
632
     * @access public
633
     * @param object Date_TimeZone $tz the Date::TimeZone object for the conversion time zone
634
     */
635
    function convertTZ($tz)
636
    {
637
        // convert to UTC
638
        if ($this->tz->getOffset($this) > 0) {
639
            $this->subtractSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
640
        } else {
641
            $this->addSeconds(intval(abs($this->tz->getOffset($this)) / 1000));
642
        }
643
        // convert UTC to new timezone
644
        if ($tz->getOffset($this) > 0) {
645
            $this->addSeconds(intval(abs($tz->getOffset($this)) / 1000));
646
        } else {
647
            $this->subtractSeconds(intval(abs($tz->getOffset($this)) / 1000));
648
        }
649
        $this->tz = $tz;
650
    }
651
 
652
    // }}}
653
    // {{{ convertTZbyID()
654
 
655
    /**
656
     * Converts this date to a new time zone, given a valid time zone ID
657
     *
658
     * Converts this date to a new time zone, given a valid time zone ID
659
     * WARNING: This may not work correctly if your system does not allow
660
     * putenv() or if localtime() does not work in your environment.  See
661
     * Date::TimeZone::inDaylightTime() for more information.
662
     *
663
     * @access public
664
     * @param string id a time zone id
665
     */
666
    function convertTZbyID($id)
667
    {
668
       if (Date_TimeZone::isValidID($id)) {
669
          $tz = new Date_TimeZone($id);
670
       } else {
671
          $tz = Date_TimeZone::getDefault();
672
       }
673
       $this->convertTZ($tz);
674
    }
675
 
676
    // }}}
677
    // {{{ toUTCbyOffset()
678
 
679
    function toUTCbyOffset($offset)
680
    {
681
        if ($offset == "Z" || $offset == "+00:00" || $offset == "+0000") {
682
            $this->toUTC();
683
            return true;
684
        }
685
 
686
        if (preg_match('/([\+\-])(\d{2}):?(\d{2})/', $offset, $regs)) {
687
            // convert offset to seconds
688
            $hours  = (int) isset($regs[2])?$regs[2]:0;
689
            $mins   = (int) isset($regs[3])?$regs[3]:0;
690
            $offset = ($hours * 3600) + ($mins * 60);
691
 
692
            if (isset($regs[1]) && $regs[1] == "-") {
693
                $offset *= -1;
694
            }
695
 
696
            if ($offset > 0) {
697
                $this->subtractSeconds(intval($offset));
698
            } else {
699
                $this->addSeconds(intval(abs($offset)));
700
            }
701
 
702
            $this->tz = new Date_TimeZone('UTC');
703
            return true;
704
        }
705
 
706
        return false;
707
    }
708
 
709
    // }}}
710
    // {{{ addSeconds()
711
 
712
    /**
713
     * Adds a given number of seconds to the date
714
     *
715
     * Adds a given number of seconds to the date
716
     *
717
     * @access public
718
     * @param int $sec the number of seconds to add
719
     */
720
    function addSeconds($sec)
721
    {
722
        settype($sec, 'int');
723
 
724
        // Negative value given.
725
        if ($sec < 0) {
726
            $this->subtractSeconds(abs($sec));
727
            return;
728
        }
729
 
730
        $this->addSpan(new Date_Span($sec));
731
    }
732
 
733
    // }}}
734
    // {{{ addSpan()
735
 
736
    /**
737
     * Adds a time span to the date
738
     *
739
     * Adds a time span to the date
740
     *
741
     * @access public
742
     * @param object Date_Span $span the time span to add
743
     */
744
    function addSpan($span)
745
    {
746
        if (!is_a($span, 'Date_Span')) {
747
            return;
748
        }
749
 
750
        $this->second += $span->second;
751
        if ($this->second >= 60) {
752
            $this->minute++;
753
            $this->second -= 60;
754
        }
755
 
756
        $this->minute += $span->minute;
757
        if ($this->minute >= 60) {
758
            $this->hour++;
759
            if ($this->hour >= 24) {
760
                list($this->year, $this->month, $this->day) =
761
                    sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
762
                $this->hour -= 24;
763
            }
764
            $this->minute -= 60;
765
        }
766
 
767
        $this->hour += $span->hour;
768
        if ($this->hour >= 24) {
769
            list($this->year, $this->month, $this->day) =
770
                sscanf(Date_Calc::nextDay($this->day, $this->month, $this->year), "%04s%02s%02s");
771
            $this->hour -= 24;
772
        }
773
 
774
        $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
775
        $d += $span->day;
776
 
777
        list($this->year, $this->month, $this->day) =
778
            sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
779
        $this->year  = intval($this->year);
780
        $this->month = intval($this->month);
781
        $this->day   = intval($this->day);
782
    }
783
 
784
    // }}}
785
    // {{{ subtractSeconds()
786
 
787
    /**
788
     * Subtracts a given number of seconds from the date
789
     *
790
     * Subtracts a given number of seconds from the date
791
     *
792
     * @access public
793
     * @param int $sec the number of seconds to subtract
794
     */
795
    function subtractSeconds($sec)
796
    {
797
        settype($sec, 'int');
798
 
799
        // Negative value given.
800
        if ($sec < 0) {
801
            $this->addSeconds(abs($sec));
802
            return;
803
        }
804
 
805
        $this->subtractSpan(new Date_Span($sec));
806
    }
807
 
808
    // }}}
809
    // {{{ subtractSpan()
810
 
811
    /**
812
     * Subtracts a time span to the date
813
     *
814
     * Subtracts a time span to the date
815
     *
816
     * @access public
817
     * @param object Date_Span $span the time span to subtract
818
     */
819
    function subtractSpan($span)
820
    {
821
        if (!is_a($span, 'Date_Span')) {
822
            return;
823
        }
824
        if ($span->isEmpty()) {
825
            return;
826
        }
827
 
828
        $this->second -= $span->second;
829
        if ($this->second < 0) {
830
            $this->minute--;
831
            $this->second += 60;
832
        }
833
 
834
        $this->minute -= $span->minute;
835
        if ($this->minute < 0) {
836
            $this->hour--;
837
            if ($this->hour < 0) {
838
                list($this->year, $this->month, $this->day) =
839
                    sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
840
                $this->hour += 24;
841
            }
842
            $this->minute += 60;
843
        }
844
 
845
        $this->hour -= $span->hour;
846
        if ($this->hour < 0) {
847
            list($this->year, $this->month, $this->day) =
848
                sscanf(Date_Calc::prevDay($this->day, $this->month, $this->year), "%04s%02s%02s");
849
            $this->hour += 24;
850
        }
851
 
852
        $d = Date_Calc::dateToDays($this->day, $this->month, $this->year);
853
        $d -= $span->day;
854
 
855
        list($this->year, $this->month, $this->day) =
856
            sscanf(Date_Calc::daysToDate($d), "%04s%02s%02s");
857
        $this->year  = intval($this->year);
858
        $this->month = intval($this->month);
859
        $this->day   = intval($this->day);
860
    }
861
 
862
    // }}}
863
    // {{{ compare()
864
 
865
    /**
866
     * Compares two dates
867
     *
868
     * Compares two dates.  Suitable for use
869
     * in sorting functions.
870
     *
871
     * @access public
872
     * @param object Date $d1 the first date
873
     * @param object Date $d2 the second date
874
     * @return int 0 if the dates are equal, -1 if d1 is before d2, 1 if d1 is after d2
875
     */
876
    function compare($d1, $d2)
877
    {
878
        $d1->convertTZ(new Date_TimeZone('UTC'));
879
        $d2->convertTZ(new Date_TimeZone('UTC'));
880
        $days1 = Date_Calc::dateToDays($d1->day, $d1->month, $d1->year);
881
        $days2 = Date_Calc::dateToDays($d2->day, $d2->month, $d2->year);
882
        if ($days1 < $days2) return -1;
883
        if ($days1 > $days2) return 1;
884
        if ($d1->hour < $d2->hour) return -1;
885
        if ($d1->hour > $d2->hour) return 1;
886
        if ($d1->minute < $d2->minute) return -1;
887
        if ($d1->minute > $d2->minute) return 1;
888
        if ($d1->second < $d2->second) return -1;
889
        if ($d1->second > $d2->second) return 1;
890
        return 0;
891
    }
892
 
893
    // }}}
894
    // {{{ before()
895
 
896
    /**
897
     * Test if this date/time is before a certain date/time
898
     *
899
     * Test if this date/time is before a certain date/time
900
     *
901
     * @access public
902
     * @param object Date $when the date to test against
903
     * @return boolean true if this date is before $when
904
     */
905
    function before($when)
906
    {
907
        if (Date::compare($this,$when) == -1) {
908
            return true;
909
        } else {
910
            return false;
911
        }
912
    }
913
 
914
    // }}}
915
    // {{{ after()
916
 
917
    /**
918
     * Test if this date/time is after a certian date/time
919
     *
920
     * Test if this date/time is after a certian date/time
921
     *
922
     * @access public
923
     * @param object Date $when the date to test against
924
     * @return boolean true if this date is after $when
925
     */
926
    function after($when)
927
    {
928
        if (Date::compare($this,$when) == 1) {
929
            return true;
930
        } else {
931
            return false;
932
        }
933
    }
934
 
935
    // }}}
936
    // {{{ equals()
937
 
938
    /**
939
     * Test if this date/time is exactly equal to a certian date/time
940
     *
941
     * Test if this date/time is exactly equal to a certian date/time
942
     *
943
     * @access public
944
     * @param object Date $when the date to test against
945
     * @return boolean true if this date is exactly equal to $when
946
     */
947
    function equals($when)
948
    {
949
        if (Date::compare($this,$when) == 0) {
950
            return true;
951
        } else {
952
            return false;
953
        }
954
    }
955
 
956
    // }}}
957
    // {{{ isFuture()
958
 
959
    /**
960
     * Determine if this date is in the future
961
     *
962
     * Determine if this date is in the future
963
     *
964
     * @access public
965
     * @return boolean true if this date is in the future
966
     */
967
    function isFuture()
968
    {
969
        $now = new Date();
970
        if ($this->after($now)) {
971
            return true;
972
        } else {
973
            return false;
974
        }
975
    }
976
 
977
    // }}}
978
    // {{{ isPast()
979
 
980
    /**
981
     * Determine if this date is in the past
982
     *
983
     * Determine if this date is in the past
984
     *
985
     * @access public
986
     * @return boolean true if this date is in the past
987
     */
988
    function isPast()
989
    {
990
        $now = new Date();
991
        if ($this->before($now)) {
992
            return true;
993
        } else {
994
            return false;
995
        }
996
    }
997
 
998
    // }}}
999
    // {{{ isLeapYear()
1000
 
1001
    /**
1002
     * Determine if the year in this date is a leap year
1003
     *
1004
     * Determine if the year in this date is a leap year
1005
     *
1006
     * @access public
1007
     * @return boolean true if this year is a leap year
1008
     */
1009
    function isLeapYear()
1010
    {
1011
        return Date_Calc::isLeapYear($this->year);
1012
    }
1013
 
1014
    // }}}
1015
    // {{{ getJulianDate()
1016
 
1017
    /**
1018
     * Get the Julian date for this date
1019
     *
1020
     * Get the Julian date for this date
1021
     *
1022
     * @access public
1023
     * @return int the Julian date
1024
     */
1025
    function getJulianDate()
1026
    {
1027
        return Date_Calc::julianDate($this->day, $this->month, $this->year);
1028
    }
1029
 
1030
    // }}}
1031
    // {{{ getDayOfWeek()
1032
 
1033
    /**
1034
     * Gets the day of the week for this date
1035
     *
1036
     * Gets the day of the week for this date (0=Sunday)
1037
     *
1038
     * @access public
1039
     * @return int the day of the week (0=Sunday)
1040
     */
1041
    function getDayOfWeek()
1042
    {
1043
        return Date_Calc::dayOfWeek($this->day, $this->month, $this->year);
1044
    }
1045
 
1046
    // }}}
1047
    // {{{ getWeekOfYear()
1048
 
1049
    /**
1050
     * Gets the week of the year for this date
1051
     *
1052
     * Gets the week of the year for this date
1053
     *
1054
     * @access public
1055
     * @return int the week of the year
1056
     */
1057
    function getWeekOfYear()
1058
    {
1059
        return Date_Calc::weekOfYear($this->day, $this->month, $this->year);
1060
    }
1061
 
1062
    // }}}
1063
    // {{{ getQuarterOfYear()
1064
 
1065
    /**
1066
     * Gets the quarter of the year for this date
1067
     *
1068
     * Gets the quarter of the year for this date
1069
     *
1070
     * @access public
1071
     * @return int the quarter of the year (1-4)
1072
     */
1073
    function getQuarterOfYear()
1074
    {
1075
        return Date_Calc::quarterOfYear($this->day, $this->month, $this->year);
1076
    }
1077
 
1078
    // }}}
1079
    // {{{ getDaysInMonth()
1080
 
1081
    /**
1082
     * Gets number of days in the month for this date
1083
     *
1084
     * Gets number of days in the month for this date
1085
     *
1086
     * @access public
1087
     * @return int number of days in this month
1088
     */
1089
    function getDaysInMonth()
1090
    {
1091
        return Date_Calc::daysInMonth($this->month, $this->year);
1092
    }
1093
 
1094
    // }}}
1095
    // {{{ getWeeksInMonth()
1096
 
1097
    /**
1098
     * Gets the number of weeks in the month for this date
1099
     *
1100
     * Gets the number of weeks in the month for this date
1101
     *
1102
     * @access public
1103
     * @return int number of weeks in this month
1104
     */
1105
    function getWeeksInMonth()
1106
    {
1107
        return Date_Calc::weeksInMonth($this->month, $this->year);
1108
    }
1109
 
1110
    // }}}
1111
    // {{{ getDayName()
1112
 
1113
    /**
1114
     * Gets the full name or abbriviated name of this weekday
1115
     *
1116
     * Gets the full name or abbriviated name of this weekday
1117
     *
1118
     * @access public
1119
     * @param boolean $abbr abbrivate the name
1120
     * @return string name of this day
1121
     */
1122
    function getDayName($abbr = false, $length = 3)
1123
    {
1124
        if ($abbr) {
1125
            return Date_Calc::getWeekdayAbbrname($this->day, $this->month, $this->year, $length);
1126
        } else {
1127
            return Date_Calc::getWeekdayFullname($this->day, $this->month, $this->year);
1128
        }
1129
    }
1130
 
1131
    // }}}
1132
    // {{{ getMonthName()
1133
 
1134
    /**
1135
     * Gets the full name or abbriviated name of this month
1136
     *
1137
     * Gets the full name or abbriviated name of this month
1138
     *
1139
     * @access public
1140
     * @param boolean $abbr abbrivate the name
1141
     * @return string name of this month
1142
     */
1143
    function getMonthName($abbr = false)
1144
    {
1145
        if ($abbr) {
1146
            return Date_Calc::getMonthAbbrname($this->month);
1147
        } else {
1148
            return Date_Calc::getMonthFullname($this->month);
1149
        }
1150
    }
1151
 
1152
    // }}}
1153
    // {{{ getNextDay()
1154
 
1155
    /**
1156
     * Get a Date object for the day after this one
1157
     *
1158
     * Get a Date object for the day after this one.
1159
     * The time of the returned Date object is the same as this time.
1160
     *
1161
     * @access public
1162
     * @return object Date Date representing the next day
1163
     */
1164
    function getNextDay()
1165
    {
1166
        $day = Date_Calc::nextDay($this->day, $this->month, $this->year, "%Y-%m-%d");
1167
        $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
1168
        $newDate = new Date();
1169
        $newDate->setDate($date);
1170
        return $newDate;
1171
    }
1172
 
1173
    // }}}
1174
    // {{{ getPrevDay()
1175
 
1176
    /**
1177
     * Get a Date object for the day before this one
1178
     *
1179
     * Get a Date object for the day before this one.
1180
     * The time of the returned Date object is the same as this time.
1181
     *
1182
     * @access public
1183
     * @return object Date Date representing the previous day
1184
     */
1185
    function getPrevDay()
1186
    {
1187
        $day = Date_Calc::prevDay($this->day, $this->month, $this->year, "%Y-%m-%d");
1188
        $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
1189
        $newDate = new Date();
1190
        $newDate->setDate($date);
1191
        return $newDate;
1192
    }
1193
 
1194
    // }}}
1195
    // {{{ getNextWeekday()
1196
 
1197
    /**
1198
     * Get a Date object for the weekday after this one
1199
     *
1200
     * Get a Date object for the weekday after this one.
1201
     * The time of the returned Date object is the same as this time.
1202
     *
1203
     * @access public
1204
     * @return object Date Date representing the next weekday
1205
     */
1206
    function getNextWeekday()
1207
    {
1208
        $day = Date_Calc::nextWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
1209
        $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
1210
        $newDate = new Date();
1211
        $newDate->setDate($date);
1212
        return $newDate;
1213
    }
1214
 
1215
    // }}}
1216
    // {{{ getPrevWeekday()
1217
 
1218
    /**
1219
     * Get a Date object for the weekday before this one
1220
     *
1221
     * Get a Date object for the weekday before this one.
1222
     * The time of the returned Date object is the same as this time.
1223
     *
1224
     * @access public
1225
     * @return object Date Date representing the previous weekday
1226
     */
1227
    function getPrevWeekday()
1228
    {
1229
        $day = Date_Calc::prevWeekday($this->day, $this->month, $this->year, "%Y-%m-%d");
1230
        $date = sprintf("%s %02d:%02d:%02d", $day, $this->hour, $this->minute, $this->second);
1231
        $newDate = new Date();
1232
        $newDate->setDate($date);
1233
        return $newDate;
1234
    }
1235
 
1236
    // }}}
1237
    // {{{ getYear()
1238
 
1239
    /**
1240
     * Returns the year field of the date object
1241
     *
1242
     * Returns the year field of the date object
1243
     *
1244
     * @access public
1245
     * @return int the year
1246
     */
1247
    function getYear()
1248
    {
1249
        return (int)$this->year;
1250
    }
1251
 
1252
    // }}}
1253
    // {{{ getMonth()
1254
 
1255
    /**
1256
     * Returns the month field of the date object
1257
     *
1258
     * Returns the month field of the date object
1259
     *
1260
     * @access public
1261
     * @return int the month
1262
     */
1263
    function getMonth()
1264
    {
1265
        return (int)$this->month;
1266
    }
1267
 
1268
    // }}}
1269
    // {{{ getDay()
1270
 
1271
    /**
1272
     * Returns the day field of the date object
1273
     *
1274
     * Returns the day field of the date object
1275
     *
1276
     * @access public
1277
     * @return int the day
1278
     */
1279
    function getDay()
1280
    {
1281
        return (int)$this->day;
1282
    }
1283
 
1284
    // }}}
1285
    // {{{ getHour()
1286
 
1287
    /**
1288
     * Returns the hour field of the date object
1289
     *
1290
     * Returns the hour field of the date object
1291
     *
1292
     * @access public
1293
     * @return int the hour
1294
     */
1295
    function getHour()
1296
    {
1297
        return $this->hour;
1298
    }
1299
 
1300
    // }}}
1301
    // {{{ getMinute()
1302
 
1303
    /**
1304
     * Returns the minute field of the date object
1305
     *
1306
     * Returns the minute field of the date object
1307
     *
1308
     * @access public
1309
     * @return int the minute
1310
     */
1311
    function getMinute()
1312
    {
1313
        return $this->minute;
1314
    }
1315
 
1316
    // }}}
1317
    // {{{ getSecond()
1318
 
1319
    /**
1320
     * Returns the second field of the date object
1321
     *
1322
     * Returns the second field of the date object
1323
     *
1324
     * @access public
1325
     * @return int the second
1326
     */
1327
    function getSecond()
1328
    {
1329
         return $this->second;
1330
    }
1331
 
1332
    // }}}
1333
    // {{{ setYear()
1334
 
1335
    /**
1336
     * Set the year field of the date object
1337
     *
1338
     * Set the year field of the date object, invalid years (not 0-9999) are set to 0.
1339
     *
1340
     * @access public
1341
     * @param int $y the year
1342
     */
1343
    function setYear($y)
1344
    {
1345
        if ($y < 0 || $y > 9999) {
1346
            $this->year = 0;
1347
        } else {
1348
            $this->year = $y;
1349
        }
1350
    }
1351
 
1352
    // }}}
1353
    // {{{ setMonth()
1354
 
1355
    /**
1356
     * Set the month field of the date object
1357
     *
1358
     * Set the month field of the date object, invalid months (not 1-12) are set to 1.
1359
     *
1360
     * @access public
1361
     * @param int $m the month
1362
     */
1363
    function setMonth($m)
1364
    {
1365
        if ($m < 1 || $m > 12) {
1366
            $this->month = 1;
1367
        } else {
1368
            $this->month = $m;
1369
        }
1370
    }
1371
 
1372
    // }}}
1373
    // {{{ setDay()
1374
 
1375
    /**
1376
     * Set the day field of the date object
1377
     *
1378
     * Set the day field of the date object, invalid days (not 1-31) are set to 1.
1379
     *
1380
     * @access public
1381
     * @param int $d the day
1382
     */
1383
    function setDay($d)
1384
    {
1385
        if ($d > 31 || $d < 1) {
1386
            $this->day = 1;
1387
        } else {
1388
            $this->day = $d;
1389
        }
1390
    }
1391
 
1392
    // }}}
1393
    // {{{ setHour()
1394
 
1395
    /**
1396
     * Set the hour field of the date object
1397
     *
1398
     * Set the hour field of the date object in 24-hour format.
1399
     * Invalid hours (not 0-23) are set to 0.
1400
     *
1401
     * @access public
1402
     * @param int $h the hour
1403
     */
1404
    function setHour($h)
1405
    {
1406
        if ($h > 23 || $h < 0) {
1407
            $this->hour = 0;
1408
        } else {
1409
            $this->hour = $h;
1410
        }
1411
    }
1412
 
1413
    // }}}
1414
    // {{{ setMinute()
1415
 
1416
    /**
1417
     * Set the minute field of the date object
1418
     *
1419
     * Set the minute field of the date object, invalid minutes (not 0-59) are set to 0.
1420
     *
1421
     * @access public
1422
     * @param int $m the minute
1423
     */
1424
    function setMinute($m)
1425
    {
1426
        if ($m > 59 || $m < 0) {
1427
            $this->minute = 0;
1428
        } else {
1429
            $this->minute = $m;
1430
        }
1431
    }
1432
 
1433
    // }}}
1434
    // {{{ setSecond()
1435
 
1436
    /**
1437
     * Set the second field of the date object
1438
     *
1439
     * Set the second field of the date object, invalid seconds (not 0-59) are set to 0.
1440
     *
1441
     * @access public
1442
     * @param int $s the second
1443
     */
1444
    function setSecond($s) {
1445
        if ($s > 59 || $s < 0) {
1446
            $this->second = 0;
1447
        } else {
1448
            $this->second = $s;
1449
        }
1450
    }
1451
 
1452
    // }}}
1453
}
1454
 
1455
// }}}
1456
 
1457
/*
1458
 * Local variables:
1459
 * mode: php
1460
 * tab-width: 4
1461
 * c-basic-offset: 4
1462
 * c-hanging-comment-ender-p: nil
1463
 * End:
1464
 */
1465
?>