1package Class::Date; 2our $AUTHORITY = 'cpan:YANICK'; 3# ABSTRACT: Class for easy date and time manipulation 4$Class::Date::VERSION = '1.1.17'; 5use 5.006; 6 7use strict; 8use vars qw( 9 @EXPORT_OK %EXPORT_TAGS @ISA 10 $DATE_FORMAT $DST_ADJUST $MONTH_BORDER_ADJUST $RANGE_CHECK 11 @NEW_FROM_SCALAR @ERROR_MESSAGES $WARNINGS 12 $DEFAULT_TIMEZONE $LOCAL_TIMEZONE $GMT_TIMEZONE 13 $NOTZ_TIMEZONE $RESTORE_TZ 14); 15use Carp; 16 17use Exporter; 18use Time::Local; 19use Class::Date::Const; 20use Scalar::Util qw(blessed); 21use POSIX; 22 23use Class::Date::Rel; 24use Class::Date::Invalid; 25 26BEGIN { 27 $WARNINGS = 1 if !defined $WARNINGS; 28 *timelocal = *Time::Local::timelocal_nocheck; 29 *timegm = *Time::Local::timegm_nocheck; 30 31 @ISA=qw(Exporter); 32 %EXPORT_TAGS = ( errors => $Class::Date::Const::EXPORT_TAGS{errors}); 33 @EXPORT_OK = (qw( date localdate gmdate now @ERROR_MESSAGES), 34 @{$EXPORT_TAGS{errors}}); 35 36 *strftime_xs = *POSIX::strftime; 37 *tzset_xs = *POSIX::tzset; 38 *tzname_xs = *POSIX::tzname; 39} 40 41$GMT_TIMEZONE = 'GMT'; 42$DST_ADJUST = 1; 43$MONTH_BORDER_ADJUST = 0; 44$RANGE_CHECK = 0; 45$RESTORE_TZ = 1; 46$DATE_FORMAT="%Y-%m-%d %H:%M:%S"; 47 48sub _set_tz { my ($tz) = @_; 49 my $lasttz = $ENV{TZ}; 50 if (!defined $tz || $tz eq $NOTZ_TIMEZONE) { 51 # warn "_set_tz: deleting TZ\n"; 52 delete $ENV{TZ}; 53 Env::C::unsetenv('TZ') if exists $INC{"Env/C.pm"}; 54 } else { 55 # warn "_set_tz: setting TZ to $tz\n"; 56 $ENV{TZ} = $tz; 57 Env::C::setenv('TZ', $tz) if exists $INC{"Env/C.pm"}; 58 } 59 tzset_xs(); 60 return $lasttz; 61} 62 63sub _set_temp_tz { my ($tz, $sub) = @_; 64 my $lasttz = _set_tz($tz); 65 my $retval = eval { $sub->(); }; 66 _set_tz($lasttz) if $RESTORE_TZ; 67 die $@ if $@; 68 return $retval; 69} 70 71tzset_xs(); 72$LOCAL_TIMEZONE = $DEFAULT_TIMEZONE = local_timezone(); 73{ 74 my $last_tz = _set_tz(undef); 75 $NOTZ_TIMEZONE = local_timezone(); 76 _set_tz($last_tz); 77} 78# warn "LOCAL: $LOCAL_TIMEZONE, NOTZ: $NOTZ_TIMEZONE\n"; 79 80# this method is used to determine what is the package name of the relative 81# time class. It is used at the operators. You only need to redefine it if 82# you want to derive both Class::Date and Class::Date::Rel. 83# Look at the Class::Date::Rel::ClassDate also. 84use constant ClassDateRel => "Class::Date::Rel"; 85use constant ClassDateInvalid => "Class::Date::Invalid"; 86 87use overload 88 '""' => "string", 89 '-' => "subtract", 90 '+' => "add", 91 '<=>' => "compare", 92 'cmp' => "compare", 93 fallback => 1; 94 95sub date ($;$) { my ($date,$tz)=@_; 96 return __PACKAGE__ -> new($date,$tz); 97} 98 99sub now () { date(time); } 100 101sub localdate ($) { date($_[0] || time, $LOCAL_TIMEZONE) } 102 103sub gmdate ($) { date($_[0] || time, $GMT_TIMEZONE) } 104 105sub import { 106 my $package=shift; 107 my @exported; 108 foreach my $symbol (@_) { 109 if ($symbol eq '-DateParse') { 110 if (!$Class::Date::DateParse++) { 111 if ( eval { require Date::Parse } ) { 112 push @NEW_FROM_SCALAR,\&new_from_scalar_date_parse; 113 } else { 114 warn "Date::Parse is not available, although it is requested by Class::Date\n" 115 if $WARNINGS; 116 } 117 } 118 } elsif ($symbol eq '-EnvC') { 119 if (!$Class::Date::EnvC++) { 120 if ( !eval { require Env::C } ) { 121 warn "Env::C is not available, although it is requested by Class::Date\n" 122 if $WARNINGS; 123 } 124 } 125 } else { 126 push @exported,$symbol; 127 } 128 }; 129 $package->export_to_level(1,$package,@exported); 130} 131 132sub new { my ($proto,$time,$tz)=@_; 133 my $class = ref($proto) || $proto; 134 135 # if the prototype is an object, not a class, then the timezone will be 136 # the same 137 $tz = $proto->[c_tz] 138 if defined($time) && !defined $tz && blessed($proto) && $proto->isa( __PACKAGE__ ); 139 140 # Default timezone is used if the timezone cannot be determined otherwise 141 $tz = $DEFAULT_TIMEZONE if !defined $tz; 142 143 return $proto->new_invalid(E_UNDEFINED,"") if !defined $time; 144 if (blessed($time) && $time->isa( __PACKAGE__ ) ) { 145 return $class->new_copy($time,$tz); 146 } elsif (blessed($time) && $time->isa('Class::Date::Rel')) { 147 return $class->new_from_scalar($time,$tz); 148 } elsif (ref($time) eq 'ARRAY') { 149 return $class->new_from_array($time,$tz); 150 } elsif (ref($time) eq 'SCALAR') { 151 return $class->new_from_scalar($$time,$tz); 152 } elsif (ref($time) eq 'HASH') { 153 return $class->new_from_hash($time,$tz); 154 } else { 155 return $class->new_from_scalar($time,$tz); 156 } 157} 158 159sub new_copy { my ($s,$input)=@_; 160 my $new_object=[ @$input ]; 161 # we don't mind $isgmt! 162 return bless($new_object, ref($s) || $s); 163} 164 165sub new_from_array { my ($s,$time,$tz) = @_; 166 my ($y,$m,$d,$hh,$mm,$ss) = @$time; 167 my $obj= [ 168 ($y||2000)-1900, ($m||1)-1, $d||1, 169 $hh||0 , $mm||0 , $ss||0 170 ]; 171 $obj->[c_tz]=$tz; 172 bless $obj, ref($s) || $s; 173 $obj->_recalc_from_struct; 174 return $obj; 175} 176 177sub new_from_hash { my ($s,$time,$tz) = @_; 178 $s->new_from_array(_array_from_hash($time),$tz); 179} 180 181sub _array_from_hash { my ($val)=@_; 182 [ 183 $val->{year} || ($val->{_year} ? $val->{_year} + 1900 : 0 ), 184 $val->{mon} || $val->{month} || ( $val->{_mon} ? $val->{_mon} + 1 : 0 ), 185 $val->{day} || $val->{mday} || $val->{day_of_month}, 186 $val->{hour}, 187 exists $val->{min} ? $val->{min} : $val->{minute}, 188 exists $val->{sec} ? $val->{sec} : $val->{second}, 189 ]; 190} 191 192sub new_from_scalar { my ($s,$time,$tz)=@_; 193 for (my $i=0;$i<@NEW_FROM_SCALAR;$i++) { 194 my $ret=$NEW_FROM_SCALAR[$i]->($s,$time,$tz); 195 return $ret if defined $ret; 196 } 197 return $s->new_invalid(E_UNPARSABLE,$time); 198} 199 200sub new_from_scalar_internal { my ($s,$time,$tz) = @_; 201 return undef if !$time; 202 203 if ($time eq 'now') { 204 # now string 205 my $obj=bless [], ref($s) || $s; 206 $obj->[c_epoch]=time; 207 $obj->[c_tz]=$tz; 208 $obj->_recalc_from_epoch; 209 return $obj; 210 } elsif ($time =~ /^\s*(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\d*\s*$/) { 211 # mysql timestamp 212 my ($y,$m,$d,$hh,$mm,$ss)=($1,$2,$3,$4,$5,$6); 213 return $s->new_from_array([$y,$m,$d,$hh,$mm,$ss],$tz); 214 } elsif ($time =~ /^\s*( \-? \d+ (\.\d+ )? )\s*$/x) { 215 # epoch secs 216 my $obj=bless [], ref($s) || $s; 217 $obj->[c_epoch]=$1; 218 $obj->[c_tz]=$tz; 219 $obj->_recalc_from_epoch; 220 return $obj; 221 } elsif ($time =~ m{ ^\s* ( \d{0,4} ) - ( \d\d? ) - ( \d\d? ) 222 ( (?: T|\s+ ) ( \d\d? ) : ( \d\d? ) ( : ( \d\d? ) (\.\d+)?)? )? }x) { 223 my ($y,$m,$d,$hh,$mm,$ss)=($1,$2,$3,$5,$6,$8); 224 # ISO(-like) date 225 return $s->new_from_array([$y,$m,$d,$hh,$mm,$ss],$tz); 226 } else { 227 return undef; 228 } 229} 230 231push @NEW_FROM_SCALAR,\&new_from_scalar_internal; 232 233sub new_from_scalar_date_parse { my ($s,$date,$tz)=@_; 234 my $lt; 235 my ($ss, $mm, $hh, $day, $month, $year, $zone) = 236 Date::Parse::strptime($date); 237 $zone = $tz if !defined $zone; 238 if ($zone eq $GMT_TIMEZONE) { 239 _set_temp_tz($zone, sub { 240 $ss = ($lt ||= [ gmtime ])->[0] if !defined $ss; 241 $mm = ($lt ||= [ gmtime ])->[1] if !defined $mm; 242 $hh = ($lt ||= [ gmtime ])->[2] if !defined $hh; 243 $day = ($lt ||= [ gmtime ])->[3] if !defined $day; 244 $month = ($lt ||= [ gmtime ])->[4] if !defined $month; 245 $year = ($lt ||= [ gmtime ])->[5] if !defined $year; 246 }); 247 } else { 248 _set_temp_tz($zone, sub { 249 $ss = ($lt ||= [ localtime ])->[0] if !defined $ss; 250 $mm = ($lt ||= [ localtime ])->[1] if !defined $mm; 251 $hh = ($lt ||= [ localtime ])->[2] if !defined $hh; 252 $day = ($lt ||= [ localtime ])->[3] if !defined $day; 253 $month = ($lt ||= [ localtime ])->[4] if !defined $month; 254 $year = ($lt ||= [ localtime ])->[5] if !defined $year; 255 }); 256 } 257 return $s->new_from_array( [$year+1900, $month+1, $day, 258 $hh, $mm, $ss], $zone); 259} 260 261sub _check_sum { my ($s) = @_; 262 my $sum=0; $sum += $_ || 0 foreach @{$s}[c_year .. c_sec]; 263 return $sum; 264} 265 266sub _recalc_from_struct { 267 my $s = shift; 268 $s->[c_isdst] = -1; 269 $s->[c_wday] = 0; 270 $s->[c_yday] = 0; 271 $s->[c_epoch] = 0; # these are required to suppress warinngs; 272 eval { 273 local $SIG{__WARN__} = sub { }; 274 my $timecalc = $s->[c_tz] eq $GMT_TIMEZONE ? 275 \&timegm : \&timelocal; 276 _set_temp_tz($s->[c_tz], 277 sub { 278 $s->[c_epoch] = $timecalc->( 279 @{$s}[c_sec,c_min,c_hour,c_day,c_mon], 280 $s->[c_year] + 1900); 281 } 282 ); 283 }; 284 return $s->_set_invalid(E_INVALID,$@) if $@; 285 my $sum = $s->_check_sum; 286 $s->_recalc_from_epoch; 287 @$s[c_error,c_errmsg] = (($s->_check_sum != $sum ? E_RANGE : 0), ""); 288 return $s->_set_invalid(E_RANGE,"") if $RANGE_CHECK && $s->[c_error]; 289 return 1; 290} 291 292sub _recalc_from_epoch { my ($s) = @_; 293 _set_temp_tz($s->[c_tz], 294 sub { 295 @{$s}[c_year..c_isdst] = 296 ($s->[c_tz] eq $GMT_TIMEZONE ? 297 gmtime($s->[c_epoch]) : localtime($s->[c_epoch])) 298 [5,4,3,2,1,0,6,7,8]; 299 } 300 ) 301} 302 303my $SETHASH = { 304 year => sub { shift->[c_year] = shift() - 1900 }, 305 _year => sub { shift->[c_year] = shift }, 306 month => sub { shift->[c_mon] = shift() - 1 }, 307 _month => sub { shift->[c_mon] = shift }, 308 day => sub { shift->[c_day] = shift }, 309 hour => sub { shift->[c_hour] = shift }, 310 min => sub { shift->[c_min] = shift }, 311 sec => sub { shift->[c_sec] = shift }, 312 tz => sub { shift->[c_tz] = shift }, 313}; 314$SETHASH->{mon} = $SETHASH->{month}; 315$SETHASH->{_mon} = $SETHASH->{_month}; 316$SETHASH->{mday} = $SETHASH->{day_of_month} = $SETHASH->{day}; 317$SETHASH->{minute} = $SETHASH->{min}; 318$SETHASH->{second} = $SETHASH->{sec}; 319 320sub clone { 321 my $s = shift; 322 my $new_date = $s->new_copy($s); 323 while (@_) { 324 my $key = shift; 325 my $value = shift; 326 $SETHASH->{$key}->($value,$new_date); 327 }; 328 $new_date->_recalc_from_struct; 329 return $new_date; 330} 331 332*set = *clone; # compatibility 333 334sub year { shift->[c_year] +1900 } 335sub _year { shift->[c_year] } 336sub yr { shift->[c_year] % 100 } 337sub mon { shift->[c_mon] +1 } 338*month = *mon; 339sub _mon { shift->[c_mon] } 340*_month = *_mon; 341sub day { shift->[c_day] } 342*day_of_month= *mday = *day; 343sub hour { shift->[c_hour] } 344sub min { shift->[c_min] } 345*minute = *min; 346sub sec { shift->[c_sec] } 347*second = *sec; 348sub wday { shift->[c_wday] + 1 } 349sub _wday { shift->[c_wday] } 350*day_of_week = *_wday; 351sub yday { shift->[c_yday] } 352*day_of_year = *yday; 353sub isdst { shift->[c_isdst] } 354*daylight_savings = \&isdst; 355sub epoch { shift->[c_epoch] } 356*as_sec = *epoch; # for compatibility 357sub tz { shift->[c_tz] } 358sub tzdst { shift->strftime("%Z") } 359 360sub monname { shift->strftime('%B') } 361*monthname = *monname; 362sub wdayname { shift->strftime('%A') } 363*day_of_weekname= *wdayname; 364 365sub error { shift->[c_error] } 366sub errmsg { my ($s) = @_; 367 sprintf $ERROR_MESSAGES[ $s->[c_error] ]."\n", $s->[c_errmsg] 368} 369*errstr = *errmsg; 370 371sub new_invalid { my ($proto,$error,$errmsg) = @_; 372 bless([],ref($proto) || $proto)->_set_invalid($error,$errmsg); 373} 374 375sub _set_invalid { my ($s,$error,$errmsg) = @_; 376 bless($s,$s->ClassDateInvalid); 377 @$s = (); 378 @$s[ci_error, ci_errmsg] = ($error,$errmsg); 379 return $s; 380} 381 382sub ampm { my ($s) = @_; 383 return $s->[c_hour] < 12 ? "AM" : "PM"; 384} 385 386sub meridiam { my ($s) = @_; 387 my $hour = $s->[c_hour] % 12; 388 if( $hour == 0 ) { $hour = 12; } 389 sprintf('%02d:%02d %s', $hour, $s->[c_min], $s->ampm); 390} 391 392sub hms { sprintf('%02d:%02d:%02d', @{ shift() }[c_hour,c_min,c_sec]) } 393 394sub ymd { my ($s)=@_; 395 sprintf('%04d/%02d/%02d', $s->year, $s->mon, $s->[c_day]) 396} 397 398sub mdy { my ($s)=@_; 399 sprintf('%02d/%02d/%04d', $s->mon, $s->[c_day], $s->year) 400} 401 402sub dmy { my ($s)=@_; 403 sprintf('%02d/%02d/%04d', $s->[c_day], $s->mon, $s->year) 404} 405 406sub array { my ($s)=@_; 407 my @return=@{$s}[c_year .. c_sec]; 408 $return[c_year]+=1900; 409 $return[c_mon]+=1; 410 @return; 411} 412 413sub aref { return [ shift()->array ] } 414*as_array = *aref; 415 416sub struct { 417 return ( @{ shift() } 418 [c_sec,c_min,c_hour,c_day,c_mon,c_year,c_wday,c_yday,c_isdst] ) 419} 420 421sub sref { return [ shift()->struct ] } 422 423sub href { my ($s)=@_; 424 my @struct=$s->struct; 425 my $h={}; 426 foreach my $key (qw(sec min hour day _month _year wday yday isdst)) { 427 $h->{$key}=shift @struct; 428 } 429 $h->{epoch} = $s->[c_epoch]; 430 $h->{year} = 1900 + $h->{_year}; 431 $h->{month} = $h->{_month} + 1; 432 $h->{minute} = $h->{min}; 433 return $h; 434} 435 436*as_hash=*href; 437 438sub hash { return %{ shift->href } } 439 440# Thanks to Tony Olekshy <olekshy@cs.ualberta.ca> for this algorithm 441# ripped from Time::Object by Matt Sergeant 442sub tzoffset { my ($s)=@_; 443 my $epoch = $s->[c_epoch]; 444 my $j = sub { # Tweaked Julian day number algorithm. 445 my ($s,$n,$h,$d,$m,$y) = @_; $m += 1; $y += 1900; 446 # Standard Julian day number algorithm without constant. 447 my $y1 = $m > 2 ? $y : $y - 1; 448 my $m1 = $m > 2 ? $m + 1 : $m + 13; 449 my $day = int(365.25 * $y1) + int(30.6001 * $m1) + $d; 450 # Modify to include hours/mins/secs in floating portion. 451 return $day + ($h + ($n + $s / 60) / 60) / 24; 452 }; 453 # Compute floating offset in hours. 454 my $delta = _set_temp_tz($s->[c_tz], 455 sub { 456 24 * (&$j(localtime $epoch) - &$j(gmtime $epoch)); 457 } 458 ); 459 # Return value in seconds rounded to nearest minute. 460 return int($delta * 60 + ($delta >= 0 ? 0.5 : -0.5)) * 60; 461} 462 463sub month_begin { my ($s) = @_; 464 my $aref = $s->aref; 465 $aref->[2] = 1; 466 return $s->new($aref); 467} 468 469sub month_end { my ($s)=@_; 470 return $s->clone(day => 1)+'1M'-'1D'; 471} 472 473sub days_in_month { 474 shift->month_end->mday; 475} 476 477sub is_leap_year { my ($s) = @_; 478 my $new_date; 479 eval { 480 $new_date = $s->new([$s->year, 2, 29],$s->tz); 481 } or return 0; 482 return $new_date->day == 29; 483} 484 485sub strftime { my ($s,$format)=@_; 486 $format ||= "%a, %d %b %Y %H:%M:%S %Z"; 487 my $fmt = _set_temp_tz($s->[c_tz], sub { strftime_xs($format,$s->struct) } ); 488 return $fmt; 489} 490 491sub string { my ($s) = @_; 492 $s->strftime($DATE_FORMAT); 493} 494 495sub subtract { my ($s,$rhs)=@_; 496 if (blessed($rhs) && $rhs->isa( __PACKAGE__ )) { 497 my $dst_adjust = 0; 498 $dst_adjust = 60*60*( $s->[c_isdst]-$rhs->[c_isdst] ) if $DST_ADJUST; 499 return $s->ClassDateRel->new($s->[c_epoch]-$rhs->[c_epoch]+$dst_adjust); 500 } elsif (blessed($rhs) && $rhs->isa("Class::Date::Rel")) { 501 return $s->add(-$rhs); 502 } elsif ($rhs) { 503 return $s->add($s->ClassDateRel->new($rhs)->neg); 504 } else { 505 return $s; 506 } 507} 508 509sub add { my ($s,$rhs)=@_; 510 local $RANGE_CHECK; 511 $rhs=$s->ClassDateRel->new($rhs) unless blessed($rhs) && $rhs->isa('Class::Date::Rel'); 512 513 return $s unless blessed($rhs) && $rhs->isa('Class::Date::Rel'); 514 515 # adding seconds 516 my $retval= $rhs->[cs_sec] ? 517 $s->new_from_scalar($s->[c_epoch]+$rhs->[cs_sec],$s->[c_tz]) : 518 $s->new_copy($s); 519 520 # adjust DST if necessary 521 if ( $DST_ADJUST && (my $dstdiff=$retval->[c_isdst]-$s->[c_isdst])) { 522 $retval->[c_epoch] -= $dstdiff*60*60; 523 $retval->_recalc_from_epoch; 524 } 525 526 # adding months 527 if ($rhs->[cs_mon]) { 528 $retval->[c_mon]+=$rhs->[cs_mon]; 529 my $year_diff= $retval->[c_mon]>0 ? # instead of POSIX::floor 530 int ($retval->[c_mon]/12) : 531 int (($retval->[c_mon]-11)/12); 532 $retval->[c_mon] -= 12*$year_diff; 533 my $expected_month = $retval->[c_mon]; 534 $retval->[c_year] += $year_diff; 535 $retval->_recalc_from_struct; 536 537 # adjust month border if necessary 538 if ($MONTH_BORDER_ADJUST && $retval && $expected_month != $retval->[c_mon]) { 539 $retval->[c_epoch] -= $retval->[c_day]*60*60*24; 540 $retval->_recalc_from_epoch; 541 } 542 } 543 544 # sigh! We have finished! 545 return $retval; 546} 547 548sub trunc { my ($s)=@_; 549 return $s->new_from_array([$s->year,$s->month,$s->day,0,0,0],$s->[c_tz]); 550} 551 552*truncate = *trunc; 553 554sub get_epochs { 555 my ($lhs,$rhs,$reverse)=@_; 556 unless (blessed($rhs) && $rhs->isa( __PACKAGE__ )) { 557 $rhs = $lhs->new($rhs); 558 } 559 my $repoch= $rhs ? $rhs->epoch : 0; 560 return $repoch, $lhs->epoch if $reverse; 561 return $lhs->epoch, $repoch; 562} 563 564sub compare { 565 my ($lhs, $rhs) = get_epochs(@_); 566 return $lhs <=> $rhs; 567} 568 569sub local_timezone { 570 return (tzname_xs())[0]; 571} 572 573sub to_tz { my ($s, $tz) = @_; 574 return $s->new($s->epoch, $tz); 575} 5761; 577 578__END__ 579 580=pod 581 582=encoding UTF-8 583 584=head1 NAME 585 586Class::Date - Class for easy date and time manipulation 587 588=head1 VERSION 589 590version 1.1.17 591 592=head1 SYNOPSIS 593 594 use Class::Date qw(:errors date localdate gmdate now -DateParse -EnvC); 595 596 # creating absolute date object (local time) 597 $date = Class::Date->new( [$year,$month,$day,$hour,$min,$sec]); 598 $date = date [$year,$month,$day,$hour,$min,$sec]; 599 # ^- "date" is an exportable function, the same as Class::Date->new 600 $date = date { year => $year, month => $month, day => $day, 601 hour => $hour, min => $min, sec => $sec }; 602 $date = date "2001-11-12 07:13:12"; 603 $date = localdate "2001-12-11"; 604 $date = now; # the same as date(time) 605 $date = date($other_date_object); # cloning 606 ... 607 608 # creating absolute date object (GMT) 609 $date = Class::Date->new( [$year,$month,$day,$hour,$min,$sec],'GMT'); 610 $date = gmdate "2001-11-12 17:13"; 611 ... 612 613 # creating absolute date object in any other timezone 614 $date = Class::Date->new( [$year,$month,$day,$hour,$min,$sec],'Iceland' ); 615 $date = date "2001-11-12 17:13", 'Iceland'; 616 $date2 = $date->new([$y2, $m2, $d2, $h2, $m2, $s2]); 617 # ^- timezone is inherited from the $date object 618 619 # creating relative date object 620 # (normally you don't need to create this object explicitly) 621 $reldate = Class::Date::Rel->new( "3Y 1M 3D 6h 2m 4s" ); 622 $reldate = Class::Date::Rel->new( "6Y" ); 623 $reldate = Class::Date::Rel->new( $secs ); # secs 624 $reldate = Class::Date::Rel->new( [$year,$month,$day,$hour,$min,$sec] ); 625 $reldate = Class::Date::Rel->new( { year => $year, month => $month, day => $day, 626 hour => $hour, min => $min, sec => $sec } ); 627 $reldate = Class::Date::Rel->new( "2001-11-12 07:13:12" ); 628 $reldate = Class::Date::Rel->new( "2001-12-11" ); 629 630 # getting values of an absolute date object 631 $date; # prints the date in default output format (see below) 632 $date->year; # year, e.g: 2001 633 $date->_year; # year - 1900, e.g. 101 634 $date->yr; # 2-digit year 0-99, e.g 1 635 $date->mon; # month 1..12 636 $date->month; # same as prev. 637 $date->_mon; # month 0..11 638 $date->_month; # same as prev. 639 $date->day; # day of month 640 $date->mday; # day of month 641 $date->day_of_month;# same as prev. 642 $date->hour; 643 $date->min; 644 $date->minute; # same as prev. 645 $date->sec; 646 $date->second; # same as prev. 647 $date->wday; # 1 = Sunday 648 $date->_wday; # 0 = Sunday 649 $date->day_of_week; # same as prev. 650 $date->yday; 651 $date->day_of_year; # same as prev. 652 $date->isdst; # DST? 653 $date->daylight_savings; # same as prev. 654 $date->epoch; # UNIX time_t 655 $date->monname; # name of month, eg: March 656 $date->monthname; # same as prev. 657 $date->wdayname; # Thursday 658 $date->day_of_weekname # same as prev. 659 $date->hms # 01:23:45 660 $date->ymd # 2000/02/29 661 $date->mdy # 02/29/2000 662 $date->dmy # 29/02/2000 663 $date->meridiam # 01:23 AM 664 $date->ampm # AM/PM 665 $date->string # 2000-02-29 12:21:11 (format can be changed, look below) 666 "$date" # same as prev. 667 $date->tzoffset # timezone-offset 668 $date->strftime($format) # POSIX strftime (without the huge POSIX.pm) 669 $date->tz # returns the base timezone as you specify, eg: CET 670 $date->tzdst # returns the real timezone with dst information, eg: CEST 671 672 ($year,$month,$day,$hour,$min,$sec)=$date->array; 673 ($year,$month,$day,$hour,$min,$sec)=@{ $date->aref }; 674 # !! $year: 1900-, $month: 1-12 675 676 ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst)=$date->struct; 677 ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst)=@{ $date->sref }; 678 # !! $year: 0-, $month: 0-11 679 680 $hash=$date->href; # $href can be reused as a constructor 681 print $hash->{year}."-".$hash->{month}. ... $hash->{sec} ... ; 682 683 %hash=$date->hash; 684 # !! $hash{year}: 1900-, $hash{month}: 1-12 685 686 $date->month_begin # First day of the month (date object) 687 $date->month_end # Last day of the month 688 $date->days_in_month # 28..31 689 690 # constructing new date based on an existing one: 691 $new_date = $date->clone; 692 $new_date = $date->clone( year => 1977, sec => 14 ); 693 # valid keys: year, _year, month, mon, _month, _mon, day, mday, day_of_month, 694 # hour, min, minute, sec, second, tz 695 # constructing a new date, which is the same as the original, but in 696 # another timezone: 697 $new_date = $date->to_tz('Iceland'); 698 699 # changing date format 700 { 701 local $Class::Date::DATE_FORMAT="%Y%m%d%H%M%S"; 702 print $date # result: 20011222000000 703 $Class::Date::DATE_FORMAT=undef; 704 print $date # result: Thu Oct 13 04:54:34 1994 705 $Class::Date::DATE_FORMAT="%Y/%m/%d" 706 print $date # result: 1994/10/13 707 } 708 709 # error handling 710 $a = date($date_string); 711 if ($a) { # valid date 712 ... 713 } else { # invalid date 714 if ($a->error == E_INVALID) { ... } 715 print $a->errstr; 716 } 717 718 # adjusting DST in calculations (see the doc) 719 $Class::Date::DST_ADJUST = 1; # this is the default 720 $Class::Date::DST_ADJUST = 0; 721 722 # "month-border adjust" flag 723 $Class::Date::MONTH_BORDER_ADJUST = 0; # this is the default 724 print date("2001-01-31")+'1M'; # will print 2001-03-03 725 $Class::Date::MONTH_BORDER_ADJUST = 1; 726 print date("2001-01-31")+'1M'; # will print 2001-02-28 727 728 # date range check 729 $Class::Date::RANGE_CHECK = 0; # this is the default 730 print date("2001-02-31"); # will print 2001-03-03 731 $Class::Date::RANGE_CHECK = 1; 732 print date("2001-02-31"); # will print nothing 733 734 # getting values of a relative date object 735 $reldate; # reldate in seconds (assumed 1 month = 2_629_744 secs) 736 $reldate->year; 737 $reldate->mon; 738 $reldate->month; # same as prev. 739 $reldate->day; 740 $reldate->hour; 741 $reldate->min; 742 $reldate->minute; # same as prev. 743 $reldate->sec; # same as $reldate 744 $reldate->second; # same as prev. 745 $reldate->sec_part; # "second" part of the relative date 746 $reldate->mon_part; # "month" part of the relative date 747 748 # arithmetic with dates: 749 print date([2001,12,11,4,5,6])->truncate; 750 # will print "2001-12-11" 751 $new_date = $date+$reldate; 752 $date2 = $date+'3Y 2D'; # 3 Years and 2 days 753 $date3 = $date+[1,2,3]; # $date plus 1 year, 2 months, 3 days 754 $date4 = $date+'3-1-5' # $date plus 3 years, 1 months, 5 days 755 756 $new_date = $date-$reldate; 757 $date2 = $date-'3Y'; # 3 Yearss 758 $date3 = $date-[1,2,3]; # $date minus 1 year, 2 months, 3 days 759 $date4 = $date-'3-1-5' # $date minus 3 years, 1 month, 5 days 760 761 $new_reldate = $date1-$date2; 762 $reldate2 = Class::Date->new('2000-11-12')-'2000-11-10'; 763 $reldate3 = $date3-'1977-11-10'; 764 765 $days_between = (Class::Date->new('2001-11-12')-'2001-07-04')->day; 766 767 # comparison between absolute dates 768 print $date1 > $date2 ? "I am older" : "I am younger"; 769 770 # comparison between relative dates 771 print $reldate1 > $reldate2 ? "I am faster" : "I am slower"; 772 773 # Adding / Subtracting months and years are sometimes tricky: 774 print date("2001-01-29") + '1M' - '1M'; # gives "2001-02-01" 775 print date("2000-02-29") + '1Y' - '1Y'; # gives "2000-03-01" 776 777 # Named interface ($date2 does not necessary to be a Class::Date object) 778 $date1->string; # same as $date1 in scalar context 779 $date1->subtract($date2); # same as $date1 - $date2 780 $date1->add($date2); # same as $date1 + $date2 781 $date1->compare($date2); # same as $date1 <=> $date2 782 783 $reldate1->sec; # same as $reldate1 in numeric or scalar context 784 $reldate1->compare($reldate2);# same as $reldate1 <=> $reldate2 785 $reldate1->add($reldate2); # same as $reldate1 + $reldate2 786 $reldate1->neg # used for subtraction 787 788 # Disabling Class::Date warnings at load time 789 BEGIN { $Class::Date::WARNINGS=0; } 790 use Class::Date; 791 792=head1 DESCRIPTION 793 794This module is intended to provide a general-purpose date and datetime type 795for perl. You have a Class::Date class for absolute date and datetime, and have 796a Class::Date::Rel class for relative dates. 797 798You can use "+", "-", "<" and ">" operators as with native perl data types. 799 800Note that this module is fairly ancient and dusty. You 801might want to take a look at L<DateTime> and its related 802modules for a more standard, and maintained, Perl date 803manipulation solution. 804 805=head1 USAGE 806 807If you want to use a date object, you need to do the following: 808 809 - create a new object 810 - do some operations (+, -, comparison) 811 - get result back 812 813=head2 Creating a new date object 814 815You can create a date object by the "date", "localdate" or "gmdate" function, 816or by calling the Class::Date constructor. 817 818"date" and "Class::Date->new" are equivalent, both has two arguments: The 819date and the timezone. 820 821 $date1= date [2000,11,12]; 822 $date2= Class::Date->new([2000,06,11,13,11,22],'GMT'); 823 $date2= $date1->new([2000,06,11,13,11,22]); 824 825If the timezone information is omitted, then it first check if "new" is 826called as an object method or a class method. If it is an object method, 827then it inherits the timezone from the base object, otherwise the default 828timezone is used ($Class::Date::DEFAULT_TIMEZONE), which is usually set to 829the local timezone (which is stored in $Class::Date::LOCAL_TIMEZONE). These 830two variables are set only once to the value, which is returned by the 831Class::Date::local_timezone() function. You can change these values 832whenever you want. 833 834"localdate $x" is equivalent to "date $x, $Class::Date::LOCAL_TIMEZONE", 835"gmdate $x" is equivalent to "date $x, $Class::Date::GMT_TIMEZONE". 836 837$Class::Date::GMT_TIMEZONE is set to 'GMT' by default. 838 839 $date1= localdate [2000,11,12]; 840 $date2= gmdate [2000,4,2,3,33,33]; 841 842 $date = localdate(time); 843 844The format of the accepted input date can be: 845 846=over 4 847 848=item [$year,$month,$day,$hour,$min,$sec] 849 850An array reference with 6 elements. The missing elements have default 851values (year: 2000, month, day: 1, hour, min, sec: 0) 852 853=item { year => $year, month => $month, day => $day, hour => $hour, min => $min, sec => $sec } 854 855A hash reference with the same 6 elements as above. 856 857=item "YYYYMMDDhhmmss" 858 859A mysql-style timestamp value, which consist of at least 14 digit. 860 861=item "973897262" 862 863A valid 32-bit integer: This is parsed as a unix time. 864 865=item "YYYY-MM-DD hh:mm:ss" 866 867A standard ISO(-like) date format. Additional ".fraction" part is ignored, 868":ss" can be omitted. 869 870=item additional input formats 871 872You can specify "-DateParse" as an import parameter, e.g: 873 874 use Class::Date qw(date -DateParse); 875 876With this, the module will try to load Date::Parse module, and if it find it then all 877these formats can be used as an input. Please refer to the Date::Parse 878documentation. 879 880=back 881 882=head2 Operations 883 884=over 4 885 886=item addition 887 888You can add the following to a Class::Date object: 889 890 - a valid Class::Date::Rel object 891 - anything, that can be used for creating a new Class::Date::Rel object 892 893It means that you don't need to create a new Class::Date::Rel object every 894time when you add something to the Class::Date object, it creates them 895automatically: 896 897 $date= Class::Date->new('2001-12-11')+Class::Date::Rel->new('3Y'); 898 899is the same as: 900 901 $date= date('2001-12-11')+'3Y'; 902 903You can provide a Class::Date::Rel object in the following form: 904 905=over 4 906 907=item array ref 908 909The same format as seen in Class::Date format, except the default values are 910different: all zero. 911 912=item hash ref 913 914The same format as seen in Class::Date format, except the default values are 915different: all zero. 916 917=item "973897262" 918 919A valid 32-bit integer is parsed as seconds. 920 921=item "YYYY-MM-DD hh:mm:ss" 922 923A standard ISO date format, but this is parsed as relative date date and time, 924so month, day and year can be zero (and defaults to zero). 925 926=item "12Y 6M 6D 20h 12m 5s" 927 928This special string can be used if you don't want to use the ISO format. This 929string consists of whitespace separated tags, each tag consists of a number and 930a unit. The units can be: 931 932 Y: year 933 M: month 934 D: day 935 h: hour 936 m: min 937 s: sec 938 939The number and unit must be written with no space between them. 940 941=back 942 943=item substraction 944 945The same rules are true for substraction, except you can substract 946two Class::Date object from each other, and you will get a Class::Date::Rel 947object: 948 949 $reldate=$date1-$date2; 950 $reldate=date('2001-11-12 12:11:07')-date('2001-10-07 10:3:21'); 951 952In this case, the "month" field of the $reldate object will be 0, 953and the other fields will contain the difference between two dates; 954 955=item comparison 956 957You can compare two Class::Date objects, or one Class::Date object and 958another data, which can be used for creating a new Class::Data object. 959 960It means that you don't need to bless both objects, one of them can be a 961simple string, array ref, hash ref, etc (see how to create a date object). 962 963 if ( date('2001-11-12') > date('2000-11-11') ) { ... } 964 965or 966 967 if ( date('2001-11-12') > '2000-11-11' ) { ... } 968 969=item truncate 970 971You can chop the time value from this object (set hour, min and sec to 0) 972with the "truncate" or "trunc" method. It does not modify the specified 973object, it returns with a new one. 974 975=item clone 976 977You can create new date object based on an existing one, by using the "clone" 978method. Note, this DOES NOT modify the base object. 979 980 $new_date = $date->clone( year => 2001, hour => 14 ); 981 982The valid keys are: year, _year, month, mon, _month, _mon, day, mday, 983day_of_month, hour, min, minute, sec, second, tz. 984 985There is a "set" method, which does the same as the "clone", it exists 986only for compatibility. 987 988=item to_tz 989 990You can use "to_tz" to create a new object, which means the same time as 991the base object, but in the different timezone. 992 993Note that $date->clone( tz => 'Iceland') and $date->to_tz('Iceland') is not 994the same! Cloning a new object with setting timezone will preserve the 995time information (hour, minute, second, etc.), but transfer the time into 996other timezone, while to_tz usually change these values based on the 997difference between the source and the destination timezone. 998 999=item Operations with Class::Date::Rel 1000 1001The Class::Date::Rel object consists of a month part and a day part. Most 1002people only use the "day" part of it. If you use both part, then you can get 1003these parts with the "sec_part" and "mon_part" method. If you use "sec", 1004"month", etc. methods or if you use this object in a mathematical context, 1005then this object is converted to one number, which is interpreted as second. 1006The conversion is based on a 30.436 days month. Don't use it too often, 1007because it is confusing... 1008 1009If you use Class::Date::Rel in an expression with other Class::Date or 1010Class::Date::Rel objects, then it does what is expected: 1011 1012 date('2001-11-12')+'1M' will be '2001-12-12' 1013 1014and 1015 1016 date('1996-02-11')+'2M' will be '1996-04-11' 1017 1018=back 1019 1020=head2 Accessing data from a Class::Date and Class::Date::Rel object 1021 1022You can use the methods methods described at the top of the document 1023if you want to access parts of the data 1024which is stored in a Class::Date and Class::Date::Rel object. 1025 1026=head2 Error handling 1027 1028If a date object became invalid, then the object will be reblessed to 1029Class::Date::Invalid. This object is false in boolean environment, so you can 1030test the date validity like this: 1031 1032 $a = date($input_date); 1033 if ($a) { # valid date 1034 ... 1035 } else { # invalid date 1036 if ($a->error == E_INVALID) { ... } 1037 print $a->errstr; 1038 } 1039 1040Note even the date is invalid, the expression "defined $a" always returns 1041true, so the following is wrong: 1042 1043 $a = date($input_date); 1044 if (defined $a) ... # WRONG!!!! 1045 1046You can test the error by getting the $date->error value. You might import 1047the ":errors" tag: 1048 1049 use Class::Date qw(:errors); 1050 1051Possible error values are: 1052 1053=over 4 1054 1055=item E_OK 1056 1057No errors. 1058 1059=item E_INVALID 1060 1061Invalid date. It is set when some of the parts of the date are invalid, and 1062Time::Local functions cannot convert them to a valid date. 1063 1064=item E_RANGE 1065 1066This error is set, when parts of the date are valid, but the whole date is 1067not valid, e.g. 2001-02-31. When the $Class::Date::RANGE_CHECK is not set, then 1068these date values are automatically converted to a valid date: 2001-03-03, 1069but the $date->error value are set to E_RANGE. If $Class::Date::RANGE_CHECK 1070is set, then a date "2001-02-31" became invalid date. 1071 1072=item E_UNPARSABLE 1073 1074This error is set, when the constructor cannot be created from a scalar, e.g: 1075 1076 $a = date("4kd sdlsdf lwekrmk"); 1077 1078=item E_UNDEFINED 1079 1080This error is set, when you want to create a date object from an undefined 1081value: 1082 1083 $a = Class::Date->new(undef); 1084 1085Note, that localdate(undef) will create a valid object, because it calls 1086$Class::Date(time). 1087 1088=back 1089 1090You can get the error in string form by calling the "errstr" method. 1091 1092=head1 DST_ADJUST 1093 1094$DST_ADJUST is an important configuration option. 1095 1096If it is set to true (default), then the module adjusts the date and time 1097when the operation switches the border of DST. With this setting, you are 1098ignoring the effect of DST. 1099 1100When $DST_ADJUST is set to false, then no adjustment is done, the 1101calculation will be based on the exact time difference. 1102 1103You will see the difference through an example: 1104 1105 $Class::Date::DST_ADJUST=1; 1106 1107 print date("2000-10-29", "CET") + "1D"; 1108 # This will print 2000-10-30 00:00:00 1109 1110 print date("2001-03-24 23:00:00", "CET") + "1D"; 1111 # This will be 2001-03-25 23:00:00 1112 1113 print date("2001-03-25", "CET") + "1D"; 1114 # This will be 2001-03-26 00:00:00 1115 1116 1117 $Class::Date::DST_ADJUST=0; 1118 1119 print date("2000-10-29", "CET") + "1D"; 1120 # This will print 2000-10-29 23:00:00 1121 1122 print date("2001-03-24 23:00:00", "CET") + "1D"; 1123 # This will be 2001-03-26 00:00:00 1124 1125=head1 MONTHS AND YEARS 1126 1127If you add or subtract "months" and "years" to a date, you may get wrong 1128dates, e.g when you add one month to 2001-01-31, you expect to get 11292001-02-31, but this date is invalid and converted to 2001-03-03. Thats' why 1130 1131 date("2001-01-31") + '1M' - '1M' != "2001-01-31" 1132 1133This problem can occur only with months and years, because others can 1134easily be converted to seconds. 1135 1136=head1 MONTH_BORDER_ADJUST 1137 1138$MONTH_BORDER_ADJUST variable is used to switch on or off the 1139month-adjust feature. This is used only when someone adds months or years to 1140a date and then the resulted date became invalid. An example: adding one 1141month to "2001-01-31" will result "2001-02-31", and this is an invalid date. 1142 1143When $MONTH_BORDER_ADJUST is false, this result simply normalized, and 1144becomes "2001-03-03". This is the default behaviour. 1145 1146When $MONTH_BORDER_ADJUST is true, this result becomes "2001-02-28". So when 1147the date overflows, then it returns the last day insted. 1148 1149Both settings keep the time information. 1150 1151=head1 TIMEZONE SUPPORT 1152 1153Since 1.0.11, Class::Date handle timezones natively on most platforms (see 1154the BUGS AND LIMITATIONS section for more info). 1155 1156When the module is loaded, then it determines the local base timezone by 1157calling the Class::Date::local_timezone() function, and stores these values 1158into two variables, these are: $Class::Date::LOCAL_TIMEZONE and 1159$Class::Date::DEFAULT_TIMEZONE. The first value is used, when you call the 1160"localdate" function, the second value is used, when you call the "date" 1161function and you don't specify the timezone. There is 1162a $Class::Date::GMT_TIMEZONE function also, which is used by the "gmdate" 1163function, this is set to 'GMT'. 1164 1165You can query the timezone of a date object by calling the $date->tz 1166method. Note this value returns the timezone as you specify, so if you 1167create the object with an unknown timezone, you will get this back. If you 1168want to query the effective timezone, you can call the $date->tzdst method. 1169This method returns only valid timezones, but it is not necessarily the 1170timezone which can be used to create a new object. For example 1171$date->tzdst can return 'CEST', which is not a valid base timezone, because 1172it contains daylight savings information also. On Linux systems, you can 1173see the possible base timezones in the /usr/share/zoneinfo directory. 1174 1175In Class::Date 1.1.6, a new environment variable is introduced: 1176$Class::Date::NOTZ_TIMEZONE. This variable stores the local timezone, which 1177is used, when the TZ environment variable is not set. It is introduced, 1178because there are some systems, which cannot handle the queried timezone 1179well. For example the local timezone is CST, it is returned by the tzname() 1180perl function, but when I set the TZ environment variable to CST, it 1181works like it would be GMT. The workaround is NOTZ_TIMEZONE: if a date 1182object has a timezone, which is the same as NOTZ_TIMEZONE, then the TZ 1183variable will be removed before each calculation. In normal case, it would 1184be the same as setting TZ to $NOTZ_TIMEZONE, but some systems don't like 1185it, so I decided to introduce this variable. The 1186$Class::Date::NOTZ_TIMEZONE variable is set in the initialization of the 1187module by removing the TZ variable from the environment and querying the 1188tzname variable. 1189 1190=head1 INTERNALS 1191 1192This module uses operator overloading very heavily. I've found it quite stable, 1193but I am afraid of it a bit. 1194 1195A Class::Date object is an array reference. 1196 1197A Class::Date::Rel object is an array reference, which contains month and 1198second information. I need to store it as an array ref, because array and month 1199values cannot be converted into seconds, because of our super calendar. 1200 1201You can add code references to the @Class::Date::NEW_FROM_SCALAR and 1202@Class::Date::Rel::NEW_FROM_SCALAR. These arrays are iterated through when a 1203scalar-format date must be parsed. These arrays only have one or two values 1204at initialization. The parameters which the code references got are the same 1205as the "new" method of each class. In this way, you can personalize the date 1206parses as you want. 1207 1208As of 0.90, the Class::Date has been rewritten. A lot of code and design 1209decision has been borrowed from Matt Sergeant's Time::Object, and there will 1210be some incompatibility with the previous public version (0.5). I tried to 1211keep compatibility methods in Class::Date. If you have problems regarding 1212this, please drop me an email with the description of the problem, and I will 1213set the compatibility back. 1214 1215Invalid dates are Class::Date::Invalid objects. Every method call on this 1216object and every operation with this object returns undef or 0. 1217 1218=head1 DEVELOPMENT FOCUS 1219 1220This module tries to be as full-featured as can be. It currently lacks 1221business-day calculation, which is planned to be implemented in the 1.0.x 1222series. 1223 1224I try to keep this module not to depend on other modules and I want this 1225module usable without a C compiler. 1226 1227Currently the module uses the POSIX localtime function very extensively. 1228This makes the date calculation a bit slow, but provides a rich interface, 1229which is not provided by any other module. When I tried to redesign the 1230internals to not depend on localtime, I failed, because there are no other 1231way to determine the daylight savings information. 1232 1233=head1 SPEED ISSUES 1234 1235There are two kind of adjustment in this module, DST_ADJUST and 1236MONTH_BORDER_ADJUST. Both of them makes the "+" and "-" operations slower. If 1237you don't need them, switch them off to achieve faster calculations. 1238 1239In general, if you really need fast date and datetime calculation, don't use 1240this module. As you see in the previous section, the focus of development is 1241not the speed in 1.0. For fast date and datetime calculations, use 1242Date::Calc module instead. 1243 1244=head1 THREAD SAFETY and MOD_PERL 1245 1246This module is NOT thread-safe, since it uses C library functions, which 1247are not thread-safe. Using this module in a multi-threaded environment can 1248cause timezones to be messed up. I did not put any warning about it, you 1249have to make sure that you understand this! 1250 1251Under some circumstances in a mod_perl environment, you require the Env::C 1252module to set the TZ variable properly before calling the time functions. I 1253added the -EnvC import option to automatically load this module if it is 1254not loaded already. Please read the mod_perl documentation about the 1255environment variables and mod_perl to get the idea why it is required 1256sometimes: 1257 1258 http://perl.apache.org/docs/2.0/user/troubleshooting/troubleshooting.html#C_Libraries_Don_t_See_C__ENV__Entries_Set_by_Perl_Code 1259 1260You are sure have this problem if the $Class::Date::NOTZ_TIMEZONE variable 1261is set to 'UTC', althought you are sure that your timezone is not that. Try 1262-EnvC in this case, but make sure that you are not using it in a 1263multi-threaded environment! 1264 1265=head1 OTHER BUGS AND LIMITATIONS 1266 1267=over 4 1268 1269=item * 1270 1271Not all date/time values can be expressed in all timezones. For example: 1272 1273 print date("2010-10-03 02:00:00", "Australia/Sydney") 1274 # it will print 2010-10-03 03:00:00 1275 1276No matter how hard you try you, you are not going to be able to express the 1277time in the example in that timezone. If you don't need the timezone 1278information and you want to make sure that the calculations are always 1279correct, please use GMT as a timezone (the 'gmdate' function can be a 1280shortcut for it). In this case, you might also consider turning off 1281DST_ADJUST to speed up the calculation. 1282 1283=item * 1284 1285I cannot manage to get the timezone code working properly on ActivePerl 12865.8.0 on win XP and earlier versions possibly have this problem also. If 1287you have a system like this, then you will have only two timezones, the 1288local and the GMT. Every timezone, which is not equal to 1289$Class::Date::GMT_TIMEZONE is assumed to be local. This seems to be caused 1290by the win32 implementation of timezone routines. I don't really know how 1291to make this thing working, so I gave up this issue. If anyone know a 1292working solution, then I will integrate it into Class::Date, but until 1293then, the timezone support will not be available for these platforms. 1294 1295=item * 1296 1297Perl 5.8.0 and earlier versions has a bug in the strftime code on some 1298operating systems (for example Linux), which is timezone related. I 1299recommend using the strftime, which is provided with Class::Date, so don't 1300try to use the module without the compiled part. The module will not work 1301with a buggy strftime - the test is hardcoded into the beginning of the 1302code. If you anyway want to use the module, remove the hardcoded "die" from 1303the module, but do it for your own risk. 1304 1305=item * 1306 1307This module uses the POSIX functions for date and 1308time calculations, so it is not working for dates beyond 2038 and before 1902. 1309 1310I don't know what systems support dates in 1902-1970 range, it may not work on 1311your system. I know it works on the Linux glibc system with perl 5.6.1 1312and 5.7.2. I know it does not work with perl 5.005_03 (it may be the bug of 1313the Time::Local module). Please report if you know any system where it does 1314_not_ work with perl 5.6.1 or later. 1315 1316I hope that someone will fix this with new time_t in libc. If you really need 1317dates over 2038 and before 1902, you need to completely rewrite this module or 1318use Date::Calc or other date modules. 1319 1320=item * 1321 1322This module uses Time::Local, and when it croaks, Class::Date returns 1323"Invalid date or time" error message. Time::Local is different in the 5.005 1324and 5.6.x (and even 5.7.x) version of perl, so the following code will 1325return different results: 1326 1327 $a = date("2006-11-11")->clone(year => -1); 1328 1329In perl 5.6.1, it returns an invalid date with error message "Invali date or 1330time", in perl 5.005 it returns an invalid date with range check error. Both 1331are false if you use them in boolean context though, only the error message 1332is different, but don't rely on the error message in this case. It however 1333works in the same way if you change other fields than "year" to an invalid 1334field. 1335 1336=back 1337 1338=head1 SUPPORT 1339 1340Class::Date is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. 1341 1342If you have questions, you can send questions directly to me: 1343 1344 dlux@dlux.hu 1345 1346=head1 WIN32 notes 1347 1348You can get a binary win32 version of Class::Date from Chris Winters' .ppd 1349repository with the following commands: 1350 1351For people using PPM2: 1352 1353 c:\> ppm 1354 PPM> set repository oi http://openinteract.sourceforge.net/ppmpackages/ 1355 PPM> set save 1356 PPM> install Class-Date 1357 1358For people using PPM3: 1359 1360 c:\> ppm 1361 PPM> repository http://openinteract.sourceforge.net/ppmpackages/ 1362 PPM> install Class-Date 1363 1364The first steps in PPM only needs to be done at the first time. Next time 1365you just run the 'install'. 1366 1367=head1 COPYRIGHT 1368 1369Copyright (c) 2001 Szabó, Balázs (dLux) 1370 1371All rights reserved. This program is free software; you can redistribute it 1372and/or modify it under the same terms as Perl itself. 1373 1374Portions Copyright (c) Matt Sergeant 1375 1376=head1 CREDITS 1377 1378 - Matt Sergeant <matt@sergeant.org> 1379 (Lots of code are borrowed from the Time::Object module) 1380 - Tatsuhiko Miyagawa <miyagawa@cpan.org> (bugfixes) 1381 - Stas Bekman <stas@stason.org> (suggestions, bugfix) 1382 - Chris Winters <chris@cwinters.com> (win32 .ppd version) 1383 - Benoit Beausejour <bbeausej@pobox.com> 1384 (Parts of the timezone code is borrowed from his Date::Handler module) 1385 1386=head1 SEE ALSO 1387 1388perl(1). 1389Date::Calc(3pm). 1390Time::Object(3pm). 1391Date::Handler(3pm). 1392 1393=head1 AUTHORS 1394 1395=over 4 1396 1397=item * 1398 1399dLux (Szabó, Balázs) <dlux@dlux.hu> 1400 1401=item * 1402 1403Gabor Szabo <szabgab@gmail.com> 1404 1405=item * 1406 1407Yanick Champoux <yanick@cpan.org> 1408 1409=back 1410 1411=head1 COPYRIGHT AND LICENSE 1412 1413This software is copyright (c) 2018, 2014, 2010, 2003 by Balázs Szabó. 1414 1415This is free software; you can redistribute it and/or modify it under 1416the same terms as the Perl 5 programming language system itself. 1417 1418=cut 1419