This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regexec.c: Latin1 chars can fold match UTF8_ALL
[perl5.git] / cpan / Time-Piece / Piece.pm
1 package Time::Piece;
2
3 use strict;
4
5 require Exporter;
6 require DynaLoader;
7 use Time::Seconds;
8 use Carp;
9 use Time::Local;
10
11 our @ISA = qw(Exporter DynaLoader);
12
13 our @EXPORT = qw(
14     localtime
15     gmtime
16 );
17
18 our %EXPORT_TAGS = (
19     ':override' => 'internal',
20     );
21
22 our $VERSION = '1.20_01';
23
24 bootstrap Time::Piece $VERSION;
25
26 my $DATE_SEP = '-';
27 my $TIME_SEP = ':';
28 my @MON_LIST = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
29 my @FULLMON_LIST = qw(January February March April May June July
30                       August September October November December);
31 my @DAY_LIST = qw(Sun Mon Tue Wed Thu Fri Sat);
32 my @FULLDAY_LIST = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday);
33
34 use constant 'c_sec' => 0;
35 use constant 'c_min' => 1;
36 use constant 'c_hour' => 2;
37 use constant 'c_mday' => 3;
38 use constant 'c_mon' => 4;
39 use constant 'c_year' => 5;
40 use constant 'c_wday' => 6;
41 use constant 'c_yday' => 7;
42 use constant 'c_isdst' => 8;
43 use constant 'c_epoch' => 9;
44 use constant 'c_islocal' => 10;
45
46 sub localtime {
47     unshift @_, __PACKAGE__ unless eval { $_[0]->isa('Time::Piece') };
48     my $class = shift;
49     my $time  = shift;
50     $time = time if (!defined $time);
51     $class->_mktime($time, 1);
52 }
53
54 sub gmtime {
55     unshift @_, __PACKAGE__ unless eval { $_[0]->isa('Time::Piece') };
56     my $class = shift;
57     my $time  = shift;
58     $time = time if (!defined $time);
59     $class->_mktime($time, 0);
60 }
61
62 sub new {
63     my $class = shift;
64     my ($time) = @_;
65     
66     my $self;
67     
68     if (defined($time)) {
69         $self = $class->localtime($time);
70     }
71     elsif (ref($class) && $class->isa(__PACKAGE__)) {
72         $self = $class->_mktime($class->epoch, $class->[c_islocal]);
73     }
74     else {
75         $self = $class->localtime();
76     }
77     
78     return bless $self, ref($class) || $class;
79 }
80
81 sub parse {
82     my $proto = shift;
83     my $class = ref($proto) || $proto;
84     my @components;
85     if (@_ > 1) {
86         @components = @_;
87     }
88     else {
89         @components = shift =~ /(\d+)$DATE_SEP(\d+)$DATE_SEP(\d+)(?:(?:T|\s+)(\d+)$TIME_SEP(\d+)(?:$TIME_SEP(\d+)))/;
90         @components = reverse(@components[0..5]);
91     }
92     return $class->new(_strftime("%s", @components));
93 }
94
95 sub _mktime {
96     my ($class, $time, $islocal) = @_;
97     $class = eval { (ref $class) && (ref $class)->isa('Time::Piece') }
98            ? ref $class
99            : $class;
100     if (ref($time)) {
101         $time->[c_epoch] = undef;
102         return wantarray ? @$time : bless [@$time[0..9], $islocal], $class;
103     }
104     _tzset();
105     my @time = $islocal ?
106             CORE::localtime($time)
107                 :
108             CORE::gmtime($time);
109     wantarray ? @time : bless [@time, $time, $islocal], $class;
110 }
111
112 my %_special_exports = (
113   localtime => sub { my $c = $_[0]; sub { $c->localtime(@_) } },
114   gmtime    => sub { my $c = $_[0]; sub { $c->gmtime(@_)    } },
115 );
116
117 sub export {
118   my ($class, $to, @methods) = @_;
119   for my $method (@methods) {
120     if (exists $_special_exports{$method}) {
121       no strict 'refs';
122       no warnings 'redefine';
123       *{$to . "::$method"} = $_special_exports{$method}->($class);
124     } else {
125       $class->SUPER::export($to, $method);
126     }
127   }
128 }
129
130 sub import {
131     # replace CORE::GLOBAL localtime and gmtime if required
132     my $class = shift;
133     my %params;
134     map($params{$_}++,@_,@EXPORT);
135     if (delete $params{':override'}) {
136         $class->export('CORE::GLOBAL', keys %params);
137     }
138     else {
139         $class->export((caller)[0], keys %params);
140     }
141 }
142
143 ## Methods ##
144
145 sub sec {
146     my $time = shift;
147     $time->[c_sec];
148 }
149
150 *second = \&sec;
151
152 sub min {
153     my $time = shift;
154     $time->[c_min];
155 }
156
157 *minute = \&min;
158
159 sub hour {
160     my $time = shift;
161     $time->[c_hour];
162 }
163
164 sub mday {
165     my $time = shift;
166     $time->[c_mday];
167 }
168
169 *day_of_month = \&mday;
170
171 sub mon {
172     my $time = shift;
173     $time->[c_mon] + 1;
174 }
175
176 sub _mon {
177     my $time = shift;
178     $time->[c_mon];
179 }
180
181 sub month {
182     my $time = shift;
183     if (@_) {
184         return $_[$time->[c_mon]];
185     }
186     elsif (@MON_LIST) {
187         return $MON_LIST[$time->[c_mon]];
188     }
189     else {
190         return $time->strftime('%b');
191     }
192 }
193
194 *monname = \&month;
195
196 sub fullmonth {
197     my $time = shift;
198     if (@_) {
199         return $_[$time->[c_mon]];
200     }
201     elsif (@FULLMON_LIST) {
202         return $FULLMON_LIST[$time->[c_mon]];
203     }
204     else {
205         return $time->strftime('%B');
206     }
207 }
208
209 sub year {
210     my $time = shift;
211     $time->[c_year] + 1900;
212 }
213
214 sub _year {
215     my $time = shift;
216     $time->[c_year];
217 }
218
219 sub yy {
220     my $time = shift;
221     my $res = $time->[c_year] % 100;
222     return $res > 9 ? $res : "0$res";
223 }
224
225 sub wday {
226     my $time = shift;
227     $time->[c_wday] + 1;
228 }
229
230 sub _wday {
231     my $time = shift;
232     $time->[c_wday];
233 }
234
235 *day_of_week = \&_wday;
236
237 sub wdayname {
238     my $time = shift;
239     if (@_) {
240         return $_[$time->[c_wday]];
241     }
242     elsif (@DAY_LIST) {
243         return $DAY_LIST[$time->[c_wday]];
244     }
245     else {
246         return $time->strftime('%a');
247     }
248 }
249
250 *day = \&wdayname;
251
252 sub fullday {
253     my $time = shift;
254     if (@_) {
255         return $_[$time->[c_wday]];
256     }
257     elsif (@FULLDAY_LIST) {
258         return $FULLDAY_LIST[$time->[c_wday]];
259     }
260     else {
261         return $time->strftime('%A');
262     }
263 }
264
265 sub yday {
266     my $time = shift;
267     $time->[c_yday];
268 }
269
270 *day_of_year = \&yday;
271
272 sub isdst {
273     my $time = shift;
274     $time->[c_isdst];
275 }
276
277 *daylight_savings = \&isdst;
278
279 # Thanks to Tony Olekshy <olekshy@cs.ualberta.ca> for this algorithm
280 sub tzoffset {
281     my $time = shift;
282     
283     return Time::Seconds->new(0) unless $time->[c_islocal];
284
285     my $epoch = $time->epoch;
286
287     my $j = sub {
288
289         my ($s,$n,$h,$d,$m,$y) = @_; $m += 1; $y += 1900;
290
291         $time->_jd($y, $m, $d, $h, $n, $s);
292
293     };
294
295     # Compute floating offset in hours.
296     #
297     # Note use of crt methods so the tz is properly set...
298     # See: http://perlmonks.org/?node_id=820347
299     my $delta = 24 * ($j->(_crt_localtime($epoch)) - $j->(_crt_gmtime($epoch)));
300
301     # Return value in seconds rounded to nearest minute.
302     return Time::Seconds->new( int($delta * 60 + ($delta >= 0 ? 0.5 : -0.5)) * 60 );
303 }
304
305 sub epoch {
306     my $time = shift;
307     if (defined($time->[c_epoch])) {
308         return $time->[c_epoch];
309     }
310     else {
311         my $epoch = $time->[c_islocal] ?
312           timelocal(@{$time}[c_sec .. c_mon], $time->[c_year]+1900)
313           :
314           timegm(@{$time}[c_sec .. c_mon], $time->[c_year]+1900);
315         $time->[c_epoch] = $epoch;
316         return $epoch;
317     }
318 }
319
320 sub hms {
321     my $time = shift;
322     my $sep = @_ ? shift(@_) : $TIME_SEP;
323     sprintf("%02d$sep%02d$sep%02d", $time->[c_hour], $time->[c_min], $time->[c_sec]);
324 }
325
326 *time = \&hms;
327
328 sub ymd {
329     my $time = shift;
330     my $sep = @_ ? shift(@_) : $DATE_SEP;
331     sprintf("%d$sep%02d$sep%02d", $time->year, $time->mon, $time->[c_mday]);
332 }
333
334 *date = \&ymd;
335
336 sub mdy {
337     my $time = shift;
338     my $sep = @_ ? shift(@_) : $DATE_SEP;
339     sprintf("%02d$sep%02d$sep%d", $time->mon, $time->[c_mday], $time->year);
340 }
341
342 sub dmy {
343     my $time = shift;
344     my $sep = @_ ? shift(@_) : $DATE_SEP;
345     sprintf("%02d$sep%02d$sep%d", $time->[c_mday], $time->mon, $time->year);
346 }
347
348 sub datetime {
349     my $time = shift;
350     my %seps = (date => $DATE_SEP, T => 'T', time => $TIME_SEP, @_);
351     return join($seps{T}, $time->date($seps{date}), $time->time($seps{time}));
352 }
353
354
355
356 # Julian Day is always calculated for UT regardless
357 # of local time
358 sub julian_day {
359     my $time = shift;
360     # Correct for localtime
361     $time = $time->gmtime( $time->epoch ) if $time->[c_islocal];
362
363     # Calculate the Julian day itself
364     my $jd = $time->_jd( $time->year, $time->mon, $time->mday,
365                         $time->hour, $time->min, $time->sec);
366
367     return $jd;
368 }
369
370 # MJD is defined as JD - 2400000.5 days
371 sub mjd {
372     return shift->julian_day - 2_400_000.5;
373 }
374
375 # Internal calculation of Julian date. Needed here so that
376 # both tzoffset and mjd/jd methods can share the code
377 # Algorithm from Hatcher 1984 (QJRAS 25, 53-55), and
378 #  Hughes et al, 1989, MNRAS, 238, 15
379 # See: http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=1989MNRAS.238.1529H&db_key=AST
380 # for more details
381
382 sub _jd {
383     my $self = shift;
384     my ($y, $m, $d, $h, $n, $s) = @_;
385
386     # Adjust input parameters according to the month
387     $y = ( $m > 2 ? $y : $y - 1);
388     $m = ( $m > 2 ? $m - 3 : $m + 9);
389
390     # Calculate the Julian Date (assuming Julian calendar)
391     my $J = int( 365.25 *( $y + 4712) )
392       + int( (30.6 * $m) + 0.5)
393         + 59
394           + $d
395             - 0.5;
396
397     # Calculate the Gregorian Correction (since we have Gregorian dates)
398     my $G = 38 - int( 0.75 * int(49+($y/100)));
399
400     # Calculate the actual Julian Date
401     my $JD = $J + $G;
402
403     # Modify to include hours/mins/secs in floating portion.
404     return $JD + ($h + ($n + $s / 60) / 60) / 24;
405 }
406
407 sub week {
408     my $self = shift;
409
410     my $J  = $self->julian_day;
411     # Julian day is independent of time zone so add on tzoffset
412     # if we are using local time here since we want the week day
413     # to reflect the local time rather than UTC
414     $J += ($self->tzoffset/(24*3600)) if $self->[c_islocal];
415
416     # Now that we have the Julian day including fractions
417     # convert it to an integer Julian Day Number using nearest
418     # int (since the day changes at midday we oconvert all Julian
419     # dates to following midnight).
420     $J = int($J+0.5);
421
422     use integer;
423     my $d4 = ((($J + 31741 - ($J % 7)) % 146097) % 36524) % 1461;
424     my $L  = $d4 / 1460;
425     my $d1 = (($d4 - $L) % 365) + $L;
426     return $d1 / 7 + 1;
427 }
428
429 sub _is_leap_year {
430     my $year = shift;
431     return (($year %4 == 0) && !($year % 100 == 0)) || ($year % 400 == 0)
432                ? 1 : 0;
433 }
434
435 sub is_leap_year {
436     my $time = shift;
437     my $year = $time->year;
438     return _is_leap_year($year);
439 }
440
441 my @MON_LAST = qw(31 28 31 30 31 30 31 31 30 31 30 31);
442
443 sub month_last_day {
444     my $time = shift;
445     my $year = $time->year;
446     my $_mon = $time->_mon;
447     return $MON_LAST[$_mon] + ($_mon == 1 ? _is_leap_year($year) : 0);
448 }
449
450 sub strftime {
451     my $time = shift;
452     my $tzname = $time->[c_islocal] ? '%Z' : 'UTC';
453     my $format = @_ ? shift(@_) : "%a, %d %b %Y %H:%M:%S $tzname";
454     if (!defined $time->[c_wday]) {
455         if ($time->[c_islocal]) {
456             return _strftime($format, CORE::localtime($time->epoch));
457         }
458         else {
459             return _strftime($format, CORE::gmtime($time->epoch));
460         }
461     }
462     return _strftime($format, (@$time)[c_sec..c_isdst]);
463 }
464
465 sub strptime {
466     my $time = shift;
467     my $string = shift;
468     my $format = @_ ? shift(@_) : "%a, %d %b %Y %H:%M:%S %Z";
469     my @vals = _strptime($string, $format);
470 #    warn(sprintf("got vals: %d-%d-%d %d:%d:%d\n", reverse(@vals)));
471     return scalar $time->_mktime(\@vals, (ref($time) ? $time->[c_islocal] : 0));
472 }
473
474 sub day_list {
475     shift if ref($_[0]) && $_[0]->isa(__PACKAGE__); # strip first if called as a method
476     my @old = @DAY_LIST;
477     if (@_) {
478         @DAY_LIST = @_;
479     }
480     return @old;
481 }
482
483 sub mon_list {
484     shift if ref($_[0]) && $_[0]->isa(__PACKAGE__); # strip first if called as a method
485     my @old = @MON_LIST;
486     if (@_) {
487         @MON_LIST = @_;
488     }
489     return @old;
490 }
491
492 sub time_separator {
493     shift if ref($_[0]) && $_[0]->isa(__PACKAGE__);
494     my $old = $TIME_SEP;
495     if (@_) {
496         $TIME_SEP = $_[0];
497     }
498     return $old;
499 }
500
501 sub date_separator {
502     shift if ref($_[0]) && $_[0]->isa(__PACKAGE__);
503     my $old = $DATE_SEP;
504     if (@_) {
505         $DATE_SEP = $_[0];
506     }
507     return $old;
508 }
509
510 use overload '""' => \&cdate,
511              'cmp' => \&str_compare,
512              'fallback' => undef;
513
514 sub cdate {
515     my $time = shift;
516     if ($time->[c_islocal]) {
517         return scalar(CORE::localtime($time->epoch));
518     }
519     else {
520         return scalar(CORE::gmtime($time->epoch));
521     }
522 }
523
524 sub str_compare {
525     my ($lhs, $rhs, $reverse) = @_;
526     if (UNIVERSAL::isa($rhs, 'Time::Piece')) {
527         $rhs = "$rhs";
528     }
529     return $reverse ? $rhs cmp $lhs->cdate : $lhs->cdate cmp $rhs;
530 }
531
532 use overload
533         '-' => \&subtract,
534         '+' => \&add;
535
536 sub subtract {
537     my $time = shift;
538     my $rhs = shift;
539     if (UNIVERSAL::isa($rhs, 'Time::Seconds')) {
540         $rhs = $rhs->seconds;
541     }
542
543     if (shift)
544     {
545         # SWAPED is set (so someone tried an expression like NOTDATE - DATE).
546         # Imitate Perl's standard behavior and return the result as if the
547         # string $time resolves to was subtracted from NOTDATE.  This way,
548         # classes which override this one and which have a stringify function
549         # that resolves to something that looks more like a number don't need
550         # to override this function.
551         return $rhs - "$time";
552     }
553     
554     if (UNIVERSAL::isa($rhs, 'Time::Piece')) {
555         return Time::Seconds->new($time->epoch - $rhs->epoch);
556     }
557     else {
558         # rhs is seconds.
559         return $time->_mktime(($time->epoch - $rhs), $time->[c_islocal]);
560     }
561 }
562
563 sub add {
564     my $time = shift;
565     my $rhs = shift;
566     if (UNIVERSAL::isa($rhs, 'Time::Seconds')) {
567         $rhs = $rhs->seconds;
568     }
569     croak "Invalid rhs of addition: $rhs" if ref($rhs);
570
571     return $time->_mktime(($time->epoch + $rhs), $time->[c_islocal]);
572 }
573
574 use overload
575         '<=>' => \&compare;
576
577 sub get_epochs {
578     my ($lhs, $rhs, $reverse) = @_;
579     if (!UNIVERSAL::isa($rhs, 'Time::Piece')) {
580         $rhs = $lhs->new($rhs);
581     }
582     if ($reverse) {
583         return $rhs->epoch, $lhs->epoch;
584     }
585     return $lhs->epoch, $rhs->epoch;
586 }
587
588 sub compare {
589     my ($lhs, $rhs) = get_epochs(@_);
590     return $lhs <=> $rhs;
591 }
592
593 sub add_months {
594     my ($time, $num_months) = @_;
595     
596     croak("add_months requires a number of months") unless defined($num_months);
597     
598     my $final_month = $time->_mon + $num_months;
599     my $num_years = 0;
600     if ($final_month > 11 || $final_month < 0) {
601         # these two ops required because we have no POSIX::floor and don't
602         # want to load POSIX.pm
603         if ($final_month < 0 && $final_month % 12 == 0) {
604             $num_years = int($final_month / 12) + 1;
605         }
606         else {
607             $num_years = int($final_month / 12);
608         }
609         $num_years-- if ($final_month < 0);
610         
611         $final_month = $final_month % 12;
612     }
613     
614     my @vals = _mini_mktime($time->sec, $time->min, $time->hour,
615                             $time->mday, $final_month, $time->year - 1900 + $num_years);
616     # warn(sprintf("got %d vals: %d-%d-%d %d:%d:%d [%d]\n", scalar(@vals), reverse(@vals), $time->[c_islocal]));
617     return scalar $time->_mktime(\@vals, $time->[c_islocal]);
618 }
619
620 sub add_years {
621     my ($time, $years) = @_;
622     $time->add_months($years * 12);
623 }
624
625 1;
626 __END__
627
628 =head1 NAME
629
630 Time::Piece - Object Oriented time objects
631
632 =head1 SYNOPSIS
633
634     use Time::Piece;
635     
636     my $t = localtime;
637     print "Time is $t\n";
638     print "Year is ", $t->year, "\n";
639
640 =head1 DESCRIPTION
641
642 This module replaces the standard localtime and gmtime functions with
643 implementations that return objects. It does so in a backwards
644 compatible manner, so that using localtime/gmtime in the way documented
645 in perlfunc will still return what you expect.
646
647 The module actually implements most of an interface described by
648 Larry Wall on the perl5-porters mailing list here:
649 http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2000-01/msg00241.html
650
651 =head1 USAGE
652
653 After importing this module, when you use localtime or gmtime in a scalar
654 context, rather than getting an ordinary scalar string representing the
655 date and time, you get a Time::Piece object, whose stringification happens
656 to produce the same effect as the localtime and gmtime functions. There is 
657 also a new() constructor provided, which is the same as localtime(), except
658 when passed a Time::Piece object, in which case it's a copy constructor. The
659 following methods are available on the object:
660
661     $t->sec                 # also available as $t->second
662     $t->min                 # also available as $t->minute
663     $t->hour                # 24 hour
664     $t->mday                # also available as $t->day_of_month
665     $t->mon                 # 1 = January
666     $t->_mon                # 0 = January
667     $t->monname             # Feb
668     $t->month               # same as $t->monname
669     $t->fullmonth           # February
670     $t->year                # based at 0 (year 0 AD is, of course 1 BC)
671     $t->_year               # year minus 1900
672     $t->yy                  # 2 digit year
673     $t->wday                # 1 = Sunday
674     $t->_wday               # 0 = Sunday
675     $t->day_of_week         # 0 = Sunday
676     $t->wdayname            # Tue
677     $t->day                 # same as wdayname
678     $t->fullday             # Tuesday
679     $t->yday                # also available as $t->day_of_year, 0 = Jan 01
680     $t->isdst               # also available as $t->daylight_savings
681
682     $t->hms                 # 12:34:56
683     $t->hms(".")            # 12.34.56
684     $t->time                # same as $t->hms
685
686     $t->ymd                 # 2000-02-29
687     $t->date                # same as $t->ymd
688     $t->mdy                 # 02-29-2000
689     $t->mdy("/")            # 02/29/2000
690     $t->dmy                 # 29-02-2000
691     $t->dmy(".")            # 29.02.2000
692     $t->datetime            # 2000-02-29T12:34:56 (ISO 8601)
693     $t->cdate               # Tue Feb 29 12:34:56 2000
694     "$t"                    # same as $t->cdate
695
696     $t->epoch               # seconds since the epoch
697     $t->tzoffset            # timezone offset in a Time::Seconds object
698
699     $t->julian_day          # number of days since Julian period began
700     $t->mjd                 # modified Julian date (JD-2400000.5 days)
701
702     $t->week                # week number (ISO 8601)
703
704     $t->is_leap_year        # true if it its
705     $t->month_last_day      # 28-31
706
707     $t->time_separator($s)  # set the default separator (default ":")
708     $t->date_separator($s)  # set the default separator (default "-")
709     $t->day_list(@days)     # set the default weekdays
710     $t->mon_list(@days)     # set the default months
711
712     $t->strftime(FORMAT)    # same as POSIX::strftime (without the overhead
713                             # of the full POSIX extension)
714     $t->strftime()          # "Tue, 29 Feb 2000 12:34:56 GMT"
715     
716     Time::Piece->strptime(STRING, FORMAT)
717                             # see strptime man page. Creates a new
718                             # Time::Piece object
719
720 =head2 Local Locales
721
722 Both wdayname (day) and monname (month) allow passing in a list to use
723 to index the name of the days against. This can be useful if you need
724 to implement some form of localisation without actually installing or
725 using locales.
726
727   my @days = qw( Dimanche Lundi Merdi Mercredi Jeudi Vendredi Samedi );
728
729   my $french_day = localtime->day(@days);
730
731 These settings can be overriden globally too:
732
733   Time::Piece::day_list(@days);
734
735 Or for months:
736
737   Time::Piece::mon_list(@months);
738
739 And locally for months:
740
741   print localtime->month(@months);
742
743 =head2 Date Calculations
744
745 It's possible to use simple addition and subtraction of objects:
746
747     use Time::Seconds;
748     
749     my $seconds = $t1 - $t2;
750     $t1 += ONE_DAY; # add 1 day (constant from Time::Seconds)
751
752 The following are valid ($t1 and $t2 are Time::Piece objects):
753
754     $t1 - $t2; # returns Time::Seconds object
755     $t1 - 42; # returns Time::Piece object
756     $t1 + 533; # returns Time::Piece object
757
758 However adding a Time::Piece object to another Time::Piece object
759 will cause a runtime error.
760
761 Note that the first of the above returns a Time::Seconds object, so
762 while examining the object will print the number of seconds (because
763 of the overloading), you can also get the number of minutes, hours,
764 days, weeks and years in that delta, using the Time::Seconds API.
765
766 In addition to adding seconds, there are two APIs for adding months and
767 years:
768
769     $t->add_months(6);
770     $t->add_years(5);
771
772 The months and years can be negative for subtractions. Note that there
773 is some "strange" behaviour when adding and subtracting months at the
774 ends of months. Generally when the resulting month is shorter than the
775 starting month then the number of overlap days is added. For example
776 subtracting a month from 2008-03-31 will not result in 2008-02-31 as this
777 is an impossible date. Instead you will get 2008-03-02. This appears to
778 be consistent with other date manipulation tools.
779
780 =head2 Date Comparisons
781
782 Date comparisons are also possible, using the full suite of "<", ">",
783 "<=", ">=", "<=>", "==" and "!=".
784
785 =head2 Date Parsing
786
787 Time::Piece has a built-in strptime() function (from FreeBSD), allowing
788 you incredibly flexible date parsing routines. For example:
789
790   my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
791                                 "%A %drd %b, %Y");
792   
793   print $t->strftime("%a, %d %b %Y");
794
795 Outputs:
796
797   Wed, 03 Nov 1943
798
799 (see, it's even smart enough to fix my obvious date bug)
800
801 For more information see "man strptime", which should be on all unix
802 systems.
803
804 Alternatively look here: http://www.unix.com/man-page/FreeBSD/3/strftime/
805
806 =head2 YYYY-MM-DDThh:mm:ss
807
808 The ISO 8601 standard defines the date format to be YYYY-MM-DD, and
809 the time format to be hh:mm:ss (24 hour clock), and if combined, they
810 should be concatenated with date first and with a capital 'T' in front
811 of the time.
812
813 =head2 Week Number
814
815 The I<week number> may be an unknown concept to some readers.  The ISO
816 8601 standard defines that weeks begin on a Monday and week 1 of the
817 year is the week that includes both January 4th and the first Thursday
818 of the year.  In other words, if the first Monday of January is the
819 2nd, 3rd, or 4th, the preceding days of the January are part of the
820 last week of the preceding year.  Week numbers range from 1 to 53.
821
822 =head2 Global Overriding
823
824 Finally, it's possible to override localtime and gmtime everywhere, by
825 including the ':override' tag in the import list:
826
827     use Time::Piece ':override';
828
829 =head1 CAVEATS
830
831 =head2 Setting $ENV{TZ} in Threads on Win32
832
833 Note that when using perl in the default build configuration on Win32
834 (specifically, when perl is built with PERL_IMPLICIT_SYS), each perl
835 interpreter maintains its own copy of the environment and only the main
836 interpreter will update the process environment seen by strftime.
837
838 Therefore, if you make changes to $ENV{TZ} from inside a thread other than
839 the main thread then those changes will not be seen by strftime if you
840 subsequently call that with the %Z formatting code. You must change $ENV{TZ}
841 in the main thread to have the desired effect in this case (and you must
842 also call _tzset() in the main thread to register the environment change).
843
844 Furthermore, remember that this caveat also applies to fork(), which is
845 emulated by threads on Win32.
846
847 =head2 Use of epoch seconds
848
849 This module internally uses the epoch seconds system that is provided via
850 the perl C<time()> function and supported by C<gmtime()> and C<localtime()>.
851
852 If your perl does not support times larger than C<2^31> seconds then this
853 module is likely to fail at processing dates beyond the year 2038. There are
854 moves afoot to fix that in perl. Alternatively use 64 bit perl. Or if none
855 of those are options, use the L<DateTime> module which has support for years
856 well into the future and past.
857
858 =head1 AUTHOR
859
860 Matt Sergeant, matt@sergeant.org
861 Jarkko Hietaniemi, jhi@iki.fi (while creating Time::Piece for core perl)
862
863 =head1 License
864
865 This module is free software, you may distribute it under the same terms
866 as Perl.
867
868 =head1 SEE ALSO
869
870 The excellent Calendar FAQ at http://www.tondering.dk/claus/calendar.html
871
872 =head1 BUGS
873
874 The test harness leaves much to be desired. Patches welcome.
875
876 =cut