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