package DateTime::Date; # $Id: Date.pm,v 1.11 2000/07/21 12:15:50 masato Exp $ ################################################################ =head1 NAME DateTime::Date - 日付クラス =cut use strict; use ObjectTemplate; use Exporter; use vars qw(@ISA @EXPORT); @ISA = qw(ObjectTemplate); @EXPORT = qw(attributes); attributes qw(year month day zero_padding); use Time::Local; use overload "++" => "Increment", "--" => "Decrement", "+=" => "Increment", "-=" => "Decrement", "<=>"=> "Compare" ; ################################################################ # static variable =head1 STATIC VARIABLES @Days_Month 一ヶ月の日数 %MonthString 文字列 =cut @DateTime::Date::Days_Month = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); %DateTime::Date::MonthString = ('ABBR' => ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'FULL' => ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']); %DateTime::Date::WeekString = ('ABBR' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'FULL' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], 'JAPANESE' => ['日', '月', '火', '水', '木', '金', '土']); ################################################################ =head2 $dt->SetTime($time); time 値をセットする =cut sub SetTime ($$) { my ($self, $time) = @_; my ($d, $m, $y) = (gmtime($time))[3..5]; $self->Set($y+1900, $m+1, $d); } =head2 $dt->Set($year, $month, $day); 年月日をセットする =cut sub Set($$$$) { my ($self, $y, $m, $d) = @_; $self->year($y); $self->month($m); $self->day($d); $self; } ################################################################ # calc week by gregolian # contributed by KKI <kki-s@geocities.co.jp> sub week($) { my $self = shift; my $y = $self->year; my $m = $self->month; $y = $y + 399 if ($m < 3); ($y + int($y/4) - int($y/100) + int($y/400) + (0, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4)[$m] + $self->day ) % 7; # (localtime(timelocal(0,0,0,$self->day,$self->month-1,$self->year)))[6]; } sub week_string($$) { my ($self, $mode) = @_; return $DateTime::Date::WeekString{uc($mode)}[$self->week]; } sub month_string ($$) { my ($self, $mode) = @_; return $DateTime::Date::MonthString{uc($mode)}[$self->month]; } ################################################################ sub convert ($$) { my ($self, $char) = @_; if ($char eq 'y'){ return $self->year-1900; } elsif ($char eq 'Y'){ return $self->year; } elsif ($char eq 'm'){ return sprintf("%02d", $self->month); } elsif ($char eq 'b'){ return $self->month_string('abbr'); } elsif ($char eq 'B'){ return $self->month_string('full'); } elsif ($char eq 'd'){ return sprintf("%02d", $self->day); } elsif ($char eq 'w'){ return $self->week; } elsif ($char eq 'a'){ return $self->week_string('abbr'); } elsif ($char eq 'A'){ return $self->week_string('full'); } else { return undef; } } ################################################################ # Increment year, month or day # # $date->Increment('1M'); or $date += '1M'; ( use overload ) =head2 $dt->Increment($q); =head2 $dt += $q; $q だけ値を増やす。 $q は '3Y', '2M', '1D' など。 =cut sub Increment ($$) { my ($self, $quantity) = @_; my ($num, $unit) = $quantity =~ /^(\d+)([YMD])$/; $num = 1 if ($num eq ''); $unit ||= 'D'; if ($unit eq 'D'){ for (1..$num){ if ($self->day < $self->DaysMonth($self->month)){ $self->day($self->day+1); } else { $self->Increment("1M"); $self->day(1); } } } elsif ($unit eq 'M'){ for (1..$num){ if ($self->month < 12){ $self->month($self->month+1); } else{ $self->month(1); $self->year($self->year+1); } } } elsif ($unit eq 'Y'){ $self->year($self->year+$num); } else { return undef; } $self; } =head2 $dt->Decrement($q); =head2 $dt -= $q; $q だけ減らす =cut sub Decrement ($;$) { my ($self, $quantity) = @_; my ($num, $unit) = $quantity =~ /^(\d+)([YMD])$/; $num = 1 if ($num eq ''); $unit ||= 'D'; if ($unit eq 'D'){ for (1..$num){ if ($self->day > 1){ $self->day($self->day-1); } else { $self->Decrement("1M"); $self->day($self->DaysMonth($self->month)); } } } elsif ($unit eq 'M'){ for (1..$num){ if ($self->month > 1){ $self->month($self->month-1); } else{ $self->month(12); $self->year($self->year-1); } } } elsif ($unit eq 'Y'){ $self->year($self->year - $num); } else { return undef; } $self; } =head2 $dt->Compare($dt2); =head2 $dt <=> $dt2; 比較する =cut sub Compare ($$) { my ($self, $obj) = @_; return ($self->year <=> $obj->year) || ($self->month <=> $obj->month) || ($self->day <=> $obj->day); } ################################################################ =head2 $dt->DaysMonth; その年月の日数 =cut sub DaysMonth ($) { my $self = shift; my $y = $self->year; my $m = $self->month; if ($m == 2 && (($y%4==0 && $y%100) || ($y%400==0))){ # leap year return 29; } else { return $DateTime::Date::Days_Month[$m]; } } 1;