########################################################################## # カレンダーのマトリックスを作成 # ########################################################################## # # たとえば引数が(2005, 1)のとき、以下のとおりの配列値を返す # # 日 月 火 水 木 金 土 # 2004-12-26 2004-12-27 2004-12-28 2004-12-29 2004-12-30 2004-12-31 2005-01-01 # 2005-01-02 2005-01-03 2005-01-04 2005-01-05 2005-01-06 2005-01-07 2005-01-08 # 2005-01-09 2005-01-10 2005-01-11 2005-01-12 2005-01-13 2005-01-14 2005-01-15 # 2005-01-16 2005-01-17 2005-01-18 2005-01-19 2005-01-20 2005-01-21 2005-01-22 # 2005-01-23 2005-01-24 2005-01-25 2005-01-26 2005-01-27 2005-01-28 2005-01-29 # 2005-01-30 2005-01-31 2005-02-01 2005-02-02 2005-02-03 2005-02-04 2005-02-05 # sub calender_matrix{ # チェック済 my $year = shift; my $month = shift; my @matrix; # 前後の年月情報を取得 my ($last_year, $last_month) = compute_month($year, $month, -1); # 先月の年月の値を取得 my ($next_year, $next_month) = compute_month($year, $month, 1); # 来月の年月の値を取得 # last_year と next_year は 去年、来年の意味ではないです # 変数のつけ方が紛らわしくなってすみません # 先月部分を作る my $last_day = month_days($last_year, $last_month); my $last_day_wdy = zeller($last_year, $last_month, $last_day); if ($last_day_wdy < 6){ for(my $i = $last_day - $last_day_wdy ; $i <= $last_day ; ++$i ){ push(@matrix, W3CDTF($last_year, $last_month, $i ) ); } } # 今月部分を作る for(my $i=1;$i<=month_days($year, $month);++$i){ push(@matrix, W3CDTF($year, $month, $i ) ); } # 来月部分を作る my $first_day_wdy = zeller($next_year, $next_month, 1); if ($first_day_wdy > 0){ foreach my $i(1 .. (7 - $first_day_wdy) ){ push(@matrix, W3CDTF($next_year, $next_month , $i ) ); } } # 作成したデータを返す return @matrix; } # # 年月日をYYYY-MM-DD の形式にして返す # sub W3CDTF{ my ($y, $m, $d) = @_; return sprintf('%04d-%02d-%02d', $y, $m, $d); } ########################################################################## # Zellerの公式 # ########################################################################## sub zeller{ # 引数 (年, 月, 日) my ($year, $month, $day) = @_; if($month < 3){ $month += 12; $year--; } return ( $year + int($year/4) - int($year/100) + int($year/400) + int( ( 13 * $month + 8 ) / 5) + $day) % 7; } ########################################################################## # ある年月の日数を返す # ########################################################################## sub month_days{ # 引数 (年, 月) my ($year, $month) = @_; my @days = (undef,31,28,31,30,31,30,31,31,30,31,30,31,); return $days[2] + 1 if ($month == 2 and leap_year($year) ); return $days[$month]; } ########################################################################## # うるう年判別 # ########################################################################## sub leap_year{ my $year = shift; return ($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0; } ########################################################################### # 年月の加減算 # ########################################################################### sub compute_month{ # 引数 (年, 月, 加減算する値) / 戻値 (年, 月) my ($year, $month, $value) = @_; my $ymonth = $year * 12 + $month - 1 + $value; return (int($ymonth / 12), $ymonth % 12 + 1); } ########################################################################### # テスト用領域 # ########################################################################### @matrix = calender_matrix(@ARGV); for($i=0;$i