1package Time::Piece; 2 3use strict; 4 5require Exporter; 6require DynaLoader; 7use Time::Seconds; 8use Carp; 9use Time::Local; 10 11our @ISA = qw(Exporter DynaLoader); 12 13our @EXPORT = qw( 14 localtime 15 gmtime 16); 17 18our %EXPORT_TAGS = ( 19 ':override' => 'internal', 20 ); 21 22our $VERSION = '1.27'; 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 78 return bless $self, ref($class) || $class; 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; 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 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 # 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 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 convert 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 } 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 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 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 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 620sub add_years { 621 my ($time, $years) = @_; 622 $time->add_months($years * 12); 623} 624 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 C<localtime> and C<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 720Note that C<localtime> and C<gmtime> are not listed above. If called as 721methods on a Time::Piece object, they act as constructors, returning a new 722Time::Piece object for the current time. In other words: they're not useful as 723methods. 724 725=head2 Local Locales 726 727Both wdayname (day) and monname (month) allow passing in a list to use 728to index the name of the days against. This can be useful if you need 729to implement some form of localisation without actually installing or 730using locales. 731 732 my @days = qw( Dimanche Lundi Merdi Mercredi Jeudi Vendredi Samedi ); 733 734 my $french_day = localtime->day(@days); 735 736These settings can be overridden globally too: 737 738 Time::Piece::day_list(@days); 739 740Or for months: 741 742 Time::Piece::mon_list(@months); 743 744And locally for months: 745 746 print localtime->month(@months); 747 748=head2 Date Calculations 749 750It's possible to use simple addition and subtraction of objects: 751 752 use Time::Seconds; 753 754 my $seconds = $t1 - $t2; 755 $t1 += ONE_DAY; # add 1 day (constant from Time::Seconds) 756 757The following are valid ($t1 and $t2 are Time::Piece objects): 758 759 $t1 - $t2; # returns Time::Seconds object 760 $t1 - 42; # returns Time::Piece object 761 $t1 + 533; # returns Time::Piece object 762 763However adding a Time::Piece object to another Time::Piece object 764will cause a runtime error. 765 766Note that the first of the above returns a Time::Seconds object, so 767while examining the object will print the number of seconds (because 768of the overloading), you can also get the number of minutes, hours, 769days, weeks and years in that delta, using the Time::Seconds API. 770 771In addition to adding seconds, there are two APIs for adding months and 772years: 773 774 $t->add_months(6); 775 $t->add_years(5); 776 777The months and years can be negative for subtractions. Note that there 778is some "strange" behaviour when adding and subtracting months at the 779ends of months. Generally when the resulting month is shorter than the 780starting month then the number of overlap days is added. For example 781subtracting a month from 2008-03-31 will not result in 2008-02-31 as this 782is an impossible date. Instead you will get 2008-03-02. This appears to 783be consistent with other date manipulation tools. 784 785=head2 Date Comparisons 786 787Date comparisons are also possible, using the full suite of "<", ">", 788"<=", ">=", "<=>", "==" and "!=". 789 790=head2 Date Parsing 791 792Time::Piece has a built-in strptime() function (from FreeBSD), allowing 793you incredibly flexible date parsing routines. For example: 794 795 my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943", 796 "%A %drd %b, %Y"); 797 798 print $t->strftime("%a, %d %b %Y"); 799 800Outputs: 801 802 Wed, 03 Nov 1943 803 804(see, it's even smart enough to fix my obvious date bug) 805 806For more information see "man strptime", which should be on all unix 807systems. 808 809Alternatively look here: http://www.unix.com/man-page/FreeBSD/3/strftime/ 810 811=head2 YYYY-MM-DDThh:mm:ss 812 813The ISO 8601 standard defines the date format to be YYYY-MM-DD, and 814the time format to be hh:mm:ss (24 hour clock), and if combined, they 815should be concatenated with date first and with a capital 'T' in front 816of the time. 817 818=head2 Week Number 819 820The I<week number> may be an unknown concept to some readers. The ISO 8218601 standard defines that weeks begin on a Monday and week 1 of the 822year is the week that includes both January 4th and the first Thursday 823of the year. In other words, if the first Monday of January is the 8242nd, 3rd, or 4th, the preceding days of the January are part of the 825last week of the preceding year. Week numbers range from 1 to 53. 826 827=head2 Global Overriding 828 829Finally, it's possible to override localtime and gmtime everywhere, by 830including the ':override' tag in the import list: 831 832 use Time::Piece ':override'; 833 834=head1 CAVEATS 835 836=head2 Setting $ENV{TZ} in Threads on Win32 837 838Note that when using perl in the default build configuration on Win32 839(specifically, when perl is built with PERL_IMPLICIT_SYS), each perl 840interpreter maintains its own copy of the environment and only the main 841interpreter will update the process environment seen by strftime. 842 843Therefore, if you make changes to $ENV{TZ} from inside a thread other than 844the main thread then those changes will not be seen by strftime if you 845subsequently call that with the %Z formatting code. You must change $ENV{TZ} 846in the main thread to have the desired effect in this case (and you must 847also call _tzset() in the main thread to register the environment change). 848 849Furthermore, remember that this caveat also applies to fork(), which is 850emulated by threads on Win32. 851 852=head2 Use of epoch seconds 853 854This module internally uses the epoch seconds system that is provided via 855the perl C<time()> function and supported by C<gmtime()> and C<localtime()>. 856 857If your perl does not support times larger than C<2^31> seconds then this 858module is likely to fail at processing dates beyond the year 2038. There are 859moves afoot to fix that in perl. Alternatively use 64 bit perl. Or if none 860of those are options, use the L<DateTime> module which has support for years 861well into the future and past. 862 863=head1 AUTHOR 864 865Matt Sergeant, matt@sergeant.org 866Jarkko Hietaniemi, jhi@iki.fi (while creating Time::Piece for core perl) 867 868=head1 COPYRIGHT AND LICENSE 869 870Copyright 2001, Larry Wall. 871 872This module is free software, you may distribute it under the same terms 873as Perl. 874 875=head1 SEE ALSO 876 877The excellent Calendar FAQ at http://www.tondering.dk/claus/calendar.html 878 879=head1 BUGS 880 881The test harness leaves much to be desired. Patches welcome. 882 883=cut 884