This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade Unicode::Normalize to 1.14.
[perl5.git] / cpan / Time-Piece / Piece.pm
CommitLineData
16433e2b
SP
1package Time::Piece;
2
3use strict;
4
5require Exporter;
6require DynaLoader;
7use Time::Seconds;
8use Carp;
9use Time::Local;
16433e2b
SP
10
11our @ISA = qw(Exporter DynaLoader);
12
13our @EXPORT = qw(
14 localtime
15 gmtime
16);
17
18our %EXPORT_TAGS = (
19 ':override' => 'internal',
20 );
21
ded2eedc 22our $VERSION = '1.20_01';
16433e2b
SP
23
24bootstrap Time::Piece $VERSION;
25
26my $DATE_SEP = '-';
27my $TIME_SEP = ':';
28my @MON_LIST = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
29my @FULLMON_LIST = qw(January February March April May June July
30 August September October November December);
31my @DAY_LIST = qw(Sun Mon Tue Wed Thu Fri Sat);
32my @FULLDAY_LIST = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday);
33
34use constant 'c_sec' => 0;
35use constant 'c_min' => 1;
36use constant 'c_hour' => 2;
37use constant 'c_mday' => 3;
38use constant 'c_mon' => 4;
39use constant 'c_year' => 5;
40use constant 'c_wday' => 6;
41use constant 'c_yday' => 7;
42use constant 'c_isdst' => 8;
43use constant 'c_epoch' => 9;
44use constant 'c_islocal' => 10;
45
46sub 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
54sub 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
62sub 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
90d55c29 78 return bless $self, ref($class) || $class;
16433e2b
SP
79}
80
81sub 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
95sub _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;
90d55c29 102 return wantarray ? @$time : bless [@$time[0..9], $islocal], $class;
16433e2b
SP
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
112my %_special_exports = (
113 localtime => sub { my $c = $_[0]; sub { $c->localtime(@_) } },
114 gmtime => sub { my $c = $_[0]; sub { $c->gmtime(@_) } },
115);
116
117sub 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
130sub 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
145sub sec {
146 my $time = shift;
147 $time->[c_sec];
148}
149
150*second = \&sec;
151
152sub min {
153 my $time = shift;
154 $time->[c_min];
155}
156
157*minute = \&min;
158
159sub hour {
160 my $time = shift;
161 $time->[c_hour];
162}
163
164sub mday {
165 my $time = shift;
166 $time->[c_mday];
167}
168
169*day_of_month = \&mday;
170
171sub mon {
172 my $time = shift;
173 $time->[c_mon] + 1;
174}
175
176sub _mon {
177 my $time = shift;
178 $time->[c_mon];
179}
180
181sub 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
196sub 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
209sub year {
210 my $time = shift;
211 $time->[c_year] + 1900;
212}
213
214sub _year {
215 my $time = shift;
216 $time->[c_year];
217}
218
219sub yy {
220 my $time = shift;
221 my $res = $time->[c_year] % 100;
222 return $res > 9 ? $res : "0$res";
223}
224
225sub wday {
226 my $time = shift;
227 $time->[c_wday] + 1;
228}
229
230sub _wday {
231 my $time = shift;
232 $time->[c_wday];
233}
234
235*day_of_week = \&_wday;
236
237sub 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
252sub 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
265sub yday {
266 my $time = shift;
267 $time->[c_yday];
268}
269
270*day_of_year = \&yday;
271
272sub 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
280sub 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 #
90d55c29
CBW
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)));
16433e2b
SP
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
305sub 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
320sub 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
328sub 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
336sub 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
342sub 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
348sub 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
358sub 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
371sub 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
382sub _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
407sub 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
429sub _is_leap_year {
430 my $year = shift;
431 return (($year %4 == 0) && !($year % 100 == 0)) || ($year % 400 == 0)
432 ? 1 : 0;
433}
434
435sub is_leap_year {
436 my $time = shift;
437 my $year = $time->year;
438 return _is_leap_year($year);
439}
440
441my @MON_LAST = qw(31 28 31 30 31 30 31 31 30 31 30 31);
442
443sub 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
450sub 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
465sub 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
474sub 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
483sub 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
492sub 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
501sub 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
510use overload '""' => \&cdate,
511 'cmp' => \&str_compare,
512 'fallback' => undef;
513
514sub 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
524sub 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
532use overload
533 '-' => \&subtract,
534 '+' => \&add;
535
536sub subtract {
537 my $time = shift;
538 my $rhs = shift;
539 if (UNIVERSAL::isa($rhs, 'Time::Seconds')) {
540 $rhs = $rhs->seconds;
541 }
e3db0d81
RGS
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 }
16433e2b
SP
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
563sub 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
574use overload
575 '<=>' => \&compare;
576
577sub 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
588sub compare {
589 my ($lhs, $rhs) = get_epochs(@_);
590 return $lhs <=> $rhs;
591}
592
124e6c84
RGS
593sub 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
90d55c29
CBW
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 }
124e6c84
RGS
609 $num_years-- if ($final_month < 0);
610
611 $final_month = $final_month % 12;
612 }
613
3df1a9e2
GA
614 my @vals = _mini_mktime($time->sec, $time->min, $time->hour,
615 $time->mday, $final_month, $time->year - 1900 + $num_years);
90d55c29 616 # warn(sprintf("got %d vals: %d-%d-%d %d:%d:%d [%d]\n", scalar(@vals), reverse(@vals), $time->[c_islocal]));
124e6c84
RGS
617 return scalar $time->_mktime(\@vals, $time->[c_islocal]);
618}
619
620sub add_years {
621 my ($time, $years) = @_;
622 $time->add_months($years * 12);
623}
624
16433e2b
SP
6251;
626__END__
627
628=head1 NAME
629
630Time::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
642This module replaces the standard localtime and gmtime functions with
643implementations that return objects. It does so in a backwards
644compatible manner, so that using localtime/gmtime in the way documented
645in perlfunc will still return what you expect.
646
647The module actually implements most of an interface described by
648Larry Wall on the perl5-porters mailing list here:
649http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2000-01/msg00241.html
650
651=head1 USAGE
652
653After importing this module, when you use localtime or gmtime in a scalar
654context, rather than getting an ordinary scalar string representing the
655date and time, you get a Time::Piece object, whose stringification happens
656to produce the same effect as the localtime and gmtime functions. There is
657also a new() constructor provided, which is the same as localtime(), except
658when passed a Time::Piece object, in which case it's a copy constructor. The
659following 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
722Both wdayname (day) and monname (month) allow passing in a list to use
723to index the name of the days against. This can be useful if you need
724to implement some form of localisation without actually installing or
725using locales.
726
727 my @days = qw( Dimanche Lundi Merdi Mercredi Jeudi Vendredi Samedi );
728
729 my $french_day = localtime->day(@days);
730
731These settings can be overriden globally too:
732
733 Time::Piece::day_list(@days);
734
735Or for months:
736
737 Time::Piece::mon_list(@months);
738
739And locally for months:
740
741 print localtime->month(@months);
742
743=head2 Date Calculations
744
745It'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
752The 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
758However adding a Time::Piece object to another Time::Piece object
759will cause a runtime error.
760
761Note that the first of the above returns a Time::Seconds object, so
762while examining the object will print the number of seconds (because
763of the overloading), you can also get the number of minutes, hours,
764days, weeks and years in that delta, using the Time::Seconds API.
765
124e6c84
RGS
766In addition to adding seconds, there are two APIs for adding months and
767years:
768
769 $t->add_months(6);
770 $t->add_years(5);
771
772The months and years can be negative for subtractions. Note that there
773is some "strange" behaviour when adding and subtracting months at the
774ends of months. Generally when the resulting month is shorter than the
775starting month then the number of overlap days is added. For example
776subtracting a month from 2008-03-31 will not result in 2008-02-31 as this
777is an impossible date. Instead you will get 2008-03-02. This appears to
778be consistent with other date manipulation tools.
779
16433e2b
SP
780=head2 Date Comparisons
781
782Date comparisons are also possible, using the full suite of "<", ">",
783"<=", ">=", "<=>", "==" and "!=".
784
785=head2 Date Parsing
786
90d55c29 787Time::Piece has a built-in strptime() function (from FreeBSD), allowing
16433e2b
SP
788you incredibly flexible date parsing routines. For example:
789
90d55c29 790 my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
16433e2b
SP
791 "%A %drd %b, %Y");
792
793 print $t->strftime("%a, %d %b %Y");
794
795Outputs:
796
797 Wed, 03 Nov 1943
798
799(see, it's even smart enough to fix my obvious date bug)
800
801For more information see "man strptime", which should be on all unix
802systems.
803
90d55c29
CBW
804Alternatively look here: http://www.unix.com/man-page/FreeBSD/3/strftime/
805
16433e2b
SP
806=head2 YYYY-MM-DDThh:mm:ss
807
808The ISO 8601 standard defines the date format to be YYYY-MM-DD, and
809the time format to be hh:mm:ss (24 hour clock), and if combined, they
810should be concatenated with date first and with a capital 'T' in front
811of the time.
812
813=head2 Week Number
814
815The I<week number> may be an unknown concept to some readers. The ISO
8168601 standard defines that weeks begin on a Monday and week 1 of the
817year is the week that includes both January 4th and the first Thursday
818of the year. In other words, if the first Monday of January is the
8192nd, 3rd, or 4th, the preceding days of the January are part of the
820last week of the preceding year. Week numbers range from 1 to 53.
821
822=head2 Global Overriding
823
824Finally, it's possible to override localtime and gmtime everywhere, by
825including the ':override' tag in the import list:
826
827 use Time::Piece ':override';
828
12016aad
SH
829=head1 CAVEATS
830
831=head2 Setting $ENV{TZ} in Threads on Win32
832
833Note that when using perl in the default build configuration on Win32
834(specifically, when perl is built with PERL_IMPLICIT_SYS), each perl
835interpreter maintains its own copy of the environment and only the main
836interpreter will update the process environment seen by strftime.
837
838Therefore, if you make changes to $ENV{TZ} from inside a thread other than
839the main thread then those changes will not be seen by strftime if you
840subsequently call that with the %Z formatting code. You must change $ENV{TZ}
841in the main thread to have the desired effect in this case (and you must
842also call _tzset() in the main thread to register the environment change).
843
8177d4d9
SH
844Furthermore, remember that this caveat also applies to fork(), which is
845emulated by threads on Win32.
846
90d55c29
CBW
847=head2 Use of epoch seconds
848
849This module internally uses the epoch seconds system that is provided via
850the perl C<time()> function and supported by C<gmtime()> and C<localtime()>.
851
852If your perl does not support times larger than C<2^31> seconds then this
853module is likely to fail at processing dates beyond the year 2038. There are
854moves afoot to fix that in perl. Alternatively use 64 bit perl. Or if none
855of those are options, use the L<DateTime> module which has support for years
856well into the future and past.
857
16433e2b
SP
858=head1 AUTHOR
859
860Matt Sergeant, matt@sergeant.org
861Jarkko Hietaniemi, jhi@iki.fi (while creating Time::Piece for core perl)
862
863=head1 License
864
865This module is free software, you may distribute it under the same terms
866as Perl.
867
868=head1 SEE ALSO
869
870The excellent Calendar FAQ at http://www.tondering.dk/claus/calendar.html
871
872=head1 BUGS
873
874The test harness leaves much to be desired. Patches welcome.
875
876=cut