#!/usr/local/bin/perl # カレンダースクリプト Ver.2.03 # Programmed by Mr.Tokin # (前に1.00をつくったのを忘れてた) # 2.00 -> 2.01 祝日の年度の修正(70->xx) # カレンダーの表示の修正 # 国民の休日の修正 # 振替休日の施行日をチェック # 2.01 -> 2.02 朝日奈系などで勝手に?...がついてくるものに対応 # ?1970xxxx以上でない場合には現在のカレンダー # を表示 # 2.02 -> 2.03 ハッピーマンデー判定ミス修正 # 2.03 -> 2.10 春分点を計算して春分の日を算出。(汗; # 2.10 -> 2.20 2003年以降の敬老の日と海の日のハッピーマンデー化 use File::Basename; chdir dirname($ENV{SCRIPT_FILENAME}); use strict; use Time::Local; # 日記やカレンダーのファイル名 my $PrefixDir="/home/tokin/r/diary"; my $SearchExpand = "txt"; my $PrefixFile="diary.shtml?"; my $YearPreFix = 1900; # ここから先は変更なし。 # ※CSSでdiv.holiday,div.saturday,div.weekdayのフォントなどを # 指定しておくとよい。 my @Week=('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); my @DayInMonth= (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); # 年〜,月,日,年〜,月,週,曜日 my %SpecialDay= ( '元旦' => [49, 0, 1, -1, 0, 0, 0 ] , '成人の日' => [49, 0,15,100, 0, 1, 1 ] , '建国記念日' => [67, 1,11, -1, 0, 0, 0 ] , # '春分の日' => [49, 2,20, -1, 0, 0, 0 ] , 'みどりの日' => [49, 3,29, -1, 0, 0, 0 ] , '憲法記念日' => [49, 4, 3, -1, 0, 0, 0 ] , '国民の休日' => [85, 4, 4, -1, 0, 0, 0 ] , 'こどもの日' => [49, 4, 5, -1, 0, 0, 0 ] , '海の日' => [96, 6,20, 103, 6, 2, 1 ] , '敬老の日' => [66, 8,15, 103, 8, 2, 1 ] , # '秋分の日' => [48, 8,23, -1, 0, 0, 0 ] , '体育の日' => [66, 9,10,100, 9, 1, 1 ] , '文化の日' => [48,10, 3, -1, 0, 0, 0 ] , '勤労感謝の日' => [48,10,23, -1, 0, 0, 0 ] , '天皇誕生日' => [89,11,23, -1, 0, 0, 0 ] ); # 春分日、秋分日はまだ計算してません。 # 1980-2099 # 春分日(3月X日のXが答えとして得られる) #X=int(20.8431+0.242194*(yyyy-1980)-int((yyyy-1980)/4)) # #秋分日(9月X日のXが答えとして得られる) #X=int(23.2488+0.242194*(yyyy-1980)-int((yyyy-1980)/4)) my ($NowSecond, $NowMinute, $NowHour, $NowDay, $NowMon, $NowYear, $NowWday, $NowYday, $NowISDST); my %SuperSpecialDay = ( '大喪の礼' => [89, 1,24], '即位の礼' => [90,10,12], '結婚の儀' => [93, 5, 9] ); # もし、日時が指定されているのであれば、ここで # 日程を指定してしまう。 my $selectmonth = $ENV{'QUERY_STRING'}; if ($selectmonth ne "") { $NowYear = substr($selectmonth,0,4) - 1900; $NowMon = substr($selectmonth,4,2) - 1; # exit 0 if (&timelocal(0,0,0,1,$NowMon,$NowYear) < 0); } if ( $NowYear < 70 ) { ($NowSecond, $NowMinute, $NowHour, $NowDay, $NowMon, $NowYear, $NowWday, $NowYday, $NowISDST) = localtime(time); } # 今月1日のデータを設定 my $FirstWday=(localtime(&timelocal(0,0,0,1,$NowMon,$NowYear)))[6]; my $Now_DayInMonth=$DayInMonth[$NowMon]; $Now_DayInMonth += 1 if (($NowMon == 1) && ($NowYear % 4 == 0)); my $WDay = $FirstWday; my $i; print qq(); print qq(); print qq(); print qq(); print qq(); print qq(); print qq(); print qq(); print qq()."\n"; print qq(); my $n_wday=$WDay; for( $i = 0; $i < $n_wday; $i++ ) { print qq(); } # 日にちを作る for ($i = 1; $i <= $Now_DayInMonth; $i++, $WDay = ($WDay + 1) % 7 ) { if ($WDay == 0) { print qq(); } elsif (&isSpecialDay($i,$NowMon,$NowYear,$WDay)) { print qq(); } elsif ($WDay == 6) { print qq(); } else { print qq(); } print "\n"; } print qq(),"\n",qq(
) , &MakeAnchor($i,$NowMon,$NowYear,$YearPreFix), qq(
) , &MakeAnchor($i,$NowMon,$NowYear,$YearPreFix), qq(
) , &MakeAnchor($i,$NowMon,$NowYear,$YearPreFix), qq(
), &MakeAnchor($i,$NowMon,$NowYear,$YearPreFix), qq(
); exit 0; # 祝日かどうかの判定 sub isSpecialDay { my ($day, $mon, $year, $wday) = @_; my $Special; my $key; keys %SpecialDay; while ( ($Special, $key) = each %SpecialDay ) { # 年数が一定以上 if ( $key->[3] > 0 ) { if ( $year >= $key->[3] ) { # ハッピーマンデー判定 return 1 if ( ($mon == $key->[4]) && ($key->[5]*7+1 <= $day) && ($key->[5]*7+7 >= $day) && ($wday == $key->[6] ) ); } else { # ハッピーマンデーになる前の祝日 return 1 if ( ($year >= $key->[0] ) && ($year < $key->[3] ) && ($mon == $key->[1] ) && ($day == $key->[2] ) ); # 振り替え休日(祝日が日曜) return 1 if ( ($year >= $key->[0] ) && ($mon == $key->[1] ) && ($day == $key->[2]+1 ) && ($wday == 1 ) && ( &timelocal(0,0,0,12,3,73) <= &timelocal(0,0,0,$day,$mon,$year) ) ); } # 祝日でないので次の祝日をチェック } else { # 祝日当日 return 1 if ( ($year >= $key->[0] ) && ($mon == $key->[1] ) && ($day == $key->[2] ) ); # 振り替え休日(祝日が日曜) return 1 if ( ($year >= $key->[0] ) && ($mon == $key->[1] ) && ($day == $key->[2]+1 ) && ($wday == 1 ) && ( &timelocal(0,0,0,12,3,73) <= &timelocal(0,0,0,$day,$mon,$year) ) ); } ## 1日前を調べて祝日なら1日後を調べて祝日 ==> 1 (国民の休日) ## ↑やめた。 }; # 春分の日かどうかの判定 my ($tmp_sec,$tmp_min,$tmp_hour, $VernalEquinoxDay,$VernalEquinoxMon,$VernalEquinoxYear, $tmp_wday,$tmp_yday,$tmp_isdst) = localtime (31556942.375*($year-70) + 6796560 + 3600*9); ## 念の為コメント、係数は1970〜2037までの春分点の時刻を最小二乗法で ## もとめたもの、6796560は1970年の春分点(UT)、3600*9は日本との時差 ## http://www.geocities.com/Athens/3116/eqindex.html return 1 if ( ($year == $VernalEquinoxYear) && ($mon == $VernalEquinoxMon ) && ($day == $VernalEquinoxDay ) ); return 1 if ( ($year == $VernalEquinoxYear) && ($mon == $VernalEquinoxMon ) && ($day == $VernalEquinoxDay+1 ) && ($wday == 1 ) && ( &timelocal(0,0,0,12,3,73) <= &timelocal(0,0,0,$day,$mon,$year) ) ); my ($tmp_sec,$tmp_min,$tmp_hour, $AutumnEquinoxDay,$AutumnEquinoxMon,$AutumnEquinoxYear, $tmp_wday,$tmp_yday,$tmp_isdst) = localtime (&timelocal(0,50,5,23,8,80)+31556942.375*($year-80)); # print "$AutumnEquinoxYear $AutumnEquinoxMon $AutumnEquinoxDay\n"; # 5:58:16 return 1 if ( ($year == $AutumnEquinoxYear) && ($mon == $AutumnEquinoxMon ) && ($day == $AutumnEquinoxDay ) ); return 1 if ( ($year == $AutumnEquinoxYear) && ($mon == $AutumnEquinoxMon ) && ($day == $AutumnEquinoxDay+1 ) && ($wday == 1 ) && ( &timelocal(0,0,0,12,3,73) <= &timelocal(0,0,0,$day,$mon,$year) ) ); ## 即位の礼などのスペシャルデー(19??/11/12) ==> 1 keys %SuperSpecialDay; while ( ($Special, $key) = each %SuperSpecialDay ) { # 祝日当日 return 1 if ( ($year == $key->[0] ) && ($mon == $key->[1] ) && ($day == $key->[2] ) ); } ## それ以外 ==> 0 return 0; } sub MakeAnchor { my($day, $mon, $year, $yearprefix) = @_; # ファイル形式をYYYYMMDDで取得 $mon++; $mon= "0".$mon if ($mon < 10); my $tmp_day = $day; $day= "0".$day if ($day < 10); $year += $yearprefix; my $FileSearch = $PrefixDir . '/' . "$year$mon" . '/' . "$year$mon$day" . "." . $SearchExpand; if( -e $FileSearch ) { my $DiaryUrl=$PrefixFile.$year.$mon.$day; return (qq($tmp_day)); } else { return $tmp_day; } }