page top
Contents ::
ホーム 画像の加工 LOTO6の研究 K2食品認定委員会 北区の散歩 Q珈琲(新琴似店) サル・サルーサ おばかTube 農園ギャラリー おすすめリンク ダウンロードコーナー
K2_UTY.pl K2_DAY.pl K2_MTH.pl K2_IMG.pl k2_TAG.pl k2_FIL.pl k2_SUB.pl



package k2;

;# -----------------------------------------------------------------------------
;# K2?LIB::PERL LIBRARY++                                                      .
;#                                                                             .
;#       DateTime Library                                                      .
;#                                                                             .
;#                             All Right Reserved, CopyRight (C) 2008 by Dr.K  .
;# -----------------------------------------------------------------------------


;#//////////////////////////////////////////////////////////////////////////////
;# Perl Package Module Import
;#//////////////////////////////////////////////////////////////////////////////
 #use strict;
 use Switch;
 use Time::Local;
 use Time::HiRes qw/gettimeofday tv_interval/;
 #require 'K2_UTY.pl';
;#//////////////////////////////////////////////////////////////////////////////


;#//////////////////////////////////////////////////////////////////////////////
;# Prototype
;#//////////////////////////////////////////////////////////////////////////////
;# 時間制御関数 x 2
;# StopWatch($sw, $no)
;# Sleep($ms)

;# 時間関係関数 x 5
;# isTime($tim)
;# Tim2hms($tim)
;# Tim2Int($tim)
;# Int2Tim($tim)
;# incTime($t1, $t2)

;#日付時間関数 x 8
;# DateStr()
;# DateInt)
;# TimeStr()
;# TimeInt()
;# TimeSecStr()
;# DateTimeStr()
;# DateTimeSecStr()
;# _get_DateTimeInt($sw)

;# 日付要素取得関数 x 5
;# EnglishMonth($ymd)
;# DaysInMonth($ymd)
;# DayOfWeekIndex($ymd)
;# DayOfWeek($ymd, $sw)
;# Day2Weeks($ymd)

;# 日付判定関数 x 4
;# isLeapYear($ymd)
;# isFuture($ymd)
;# isDate($ymd)
;# isDateFormat($ymd)

;# 日付変換関数 x 8
;# Day2ymd($ymd)
;# Day2Int($ymd)
;# Int2Day($ymd)
;# ymd2fix(4ymd)
;# ymd2ngp($ymd)
;# ngp2ymd($ymd)
;# toWareki($ymd)
;# toSeireki($ymd)

;# 日付計算関数 x 5
;# Age($ymd)
;# incYear($ymd)
;# incMonth($ymd)
;# incDay($ymd)
;# SpanDays($ymd, $ymd)

;# 春分、秋分、休日、旧暦、干支関数 x 8
;# Factor2Day($y, $m, $n, $w)
;# HolidayDef($y, $hn, $hd);
;# EquinoxDay($ymd)
;# isEquinox($ymd)
;# isHoliday($ymd)
;# HolidayAll($ymd)
;# Kyureki($m)
;# Junishi($y)

;# Total = 52
;#//////////////////////////////////////////////////////////////////////////////



;#//////////////////////////////////////////////////////////////////////////////
;# 時間制御関数
;#//////////////////////////////////////////////////////////////////////////////


# ストップウオッチ(精度1/100,000sec)
# $sw=1 -> start, sw=2 -> lap, sw=2 -> end
my ($UTY_SWHST, $UTY_SWHED);
sub StopWatch{
	my ($sw, $no) = @_;
	my $ret = 0;

	$sw = MinMax($sw, 1, 2);
	switch($sw){
		case 1 {
			$ret = 1;
			$UTY_SWHST = [gettimeofday];
		}
		case 2 {
			$UTY_SWHED = [gettimeofday];
			if($UTY_SWHST){
				$no = ($no) ? $no : 0;
				$no = MinMax($no, 0, 6);
				$ret = Round(tv_interval($UTY_SWHST, $UTY_SWHED), $no);
				$ret = k2::CommaFloat($ret, $no);
				$ret = LeftStr($ret, length($ret) - 1)if(RightStr($ret, 1) eq '.');
			}
		}
	}
	return($ret);
}

# スリープ(1秒以下)
# 精度(1/1000sec)
# Sleep(0.5)
sub Sleep{
	my ($ms) = @_;
	my $ret = select(undef, undef, undef, $ms);
	return($ret);
}


;#//////////////////////////////////////////////////////////////////////////////
;# 時間関係関数
;# k2::Time Format = 'hh:mm(:ss)' or 'hhmm(ss)'
;#//////////////////////////////////////////////////////////////////////////////


# 時間フォーマット判定
# hhmm(ss) or hh:mm(:ss)
sub isTime{
	my ($tim) = @_;
	my $ret = 0;
	$tim =~ s/\://g;
	my $ln = length($tim);
	if(($ln >= 4) && ($ln <= 6)){
		my $h = MidStr($tim, 1, 2);
		my $m = MidStr($tim, 3, 2);
		my $s = MidStr($tim, 5, 2);
		if(isNumeric($h.$m.$s)){
			$ret = (($h < 24) && ($m < 60) && ($s < 60)) ? 1 : 0;
		}
	}
	return($ret);
}

# 時間を要素に分ける
# hh:mm(:ss) -> hhmm(ss)
# hh:mm(:ss) -> (hh, mm(, ss))
sub Tim2hms{
	my ($tim) = @_;
	my($h, $m, $s, @ret);
	if($tim =~ /(\d+)\:(\d+)\:(\d+)/){
		$tim =~ s/(\d+)\:(\d+)\:(\d+)//;
		$h = RightStr('00'.$1, 2);
		$m = RightStr('00'.$2, 2);
		$s = RightStr('00'.$3, 2);
		@ret = ($h, $m, $s);
	}elsif($tim =~ /(\d+)\:(\d+)/){
		$tim =~ s/(\d+)\:(\d+)//;
		$h = RightStr('00'.$1, 2);
		$m = RightStr('00'.$2, 2);
		@ret = ($h, $m);
	}else{
		my $ln = length($tim);
		if($ln == 6){
			$h = MidStr($tim, 1, 2);
			$m = MidStr($tim, 3, 2);
			$s = MidStr($tim, 5, 2);
			@ret = ($h, $m, $s);
		}elsif($ln == 4){
			$h = MidStr($tim, 1, 2);
			$m = MidStr($tim, 3, 2);
			@ret = ($h, $m);
		}
	}
	if(wantarray){return(@ret)}
	else         {return(Joint('', @ret))}
}

# 時間フォーマットを数値に変換
# hh:mm(:ss) -> hhmm(ss)
sub Tim2Int{
	my ($tim) = @_;
	return(Tim2hms($tim));
}

# 数値を時間フォーマットに変換
# hhmm(ss) -> hh:mm(:ss)
sub Int2Tim{
	my ($tim) = @_;
	$tim = Joint(':', Tim2hms($tim));
	return($tim);
}

# 時間の加減算($t1±$t2)
# 99時間まで加減算できる
# 'hhmm(ss)', '±hhmm(ss)'
# 'hh:mm(:ss)', '±hh:mm(:ss)'
# 'yyyymmdd hhmm(ss)', '±hhmm(ss)'
# 'yyyy/mm/dd hh:mm(:ss)', '±hh:mm(:ss)'
sub incTime{
	my ($t1, $t2) = @_;

	my $sign = ($t2 =~ /^\-/) ? -1 : 1;
	$t2 =~ s/^[+-]//g;

	my ($yy, $mm, $dd) = (2000, 1, 1);
	my ($ret, $pt) = ('', 0);

	$pt = PosStr(' ', $t1);
	if($pt){
		($yy, $mm, $dd) = Day2ymd(LeftStr($t1, $pt - 1));
		$t1 = RightStr($t1, length($t1) - $pt);
	}

	my ($h1, $m1, $s1) = (0, 0, 0);
	my ($h2, $m2, $s2) = (0, 0, 0);
	($h1, $m1, $s1) = Tim2hms($t1);
	($h2, $m2, $s2) = Tim2hms($t2);

	my $sec = $h2 * 24 * 60 * 60 + $m2 * 60 + $s2;
	my $day = timelocal($s1, $m1, $h1, $dd, $mm - 1, $yy) + $sign * $sec;
	my @s = localtime($day);

	# isDate+
	if($pt){
		# yyyy/mm/dd hh:mm:ss
		$ret = sprintf("%04d/%02d/%02d %02d:%02d:%02d",
						$s[5] + 1900, $s[4] + 1, $s[3] ,$s[2] ,$s[1] ,$s[0]);
	}else{
		# hh:mm:ss
		$ret = sprintf("%02d:%02d:%02d", $s[2], $s[1], $s[0]);
	}
	return($ret);
}

;#//////////////////////////////////////////////////////////////////////////////
;# 日付時間関数
;#//////////////////////////////////////////////////////////////////////////////


# サーバータイムの取得(内部関数)
sub _get_DateTimeInt{
	my ($sw) = @_;

	my $ret = '';
	my @tm = localtime(time);
	## 0:Date, 1:Time, 2: DateTime ##
	switch($sw){
		case 0 {$ret = sprintf("%4d%02d%02d", $tm[5]+1900, $tm[4]+1, $tm[3])}
		case 1 {$ret = sprintf("%02d%02d%02d", $tm[2], $tm[1], $tm[0])}
		case 2 {$ret = sprintf("%4d%02d%02d%02d%02d%02d",
						$tm[5]+1900, $tm[4]+1, $tm[3], $tm[2], $tm[1], $tm[0])}
		else   {$ret = ''}
	}
	return($ret);
}

# 日付を'yyy/mm/dd'で取得
sub DateStr{
	my $day = _get_DateTimeInt(0);
	$day = Int2Day($day);
	return($day);
}

# 日付を'yyymmdd'で取得
sub DateInt{
	my $day = _get_DateTimeInt(0);
	return($day);
}

# 時間を'hh:mm'で取得
sub TimeStr{
	my $tim = _get_DateTimeInt(1);
	$tim = LeftStr(Int2Tim($tim), 5);
	return($tim);
}

# 時間を'hh:mm:ss'で取得
sub TimeSecStr{
	my $tim = _get_DateTimeInt(2);
	$tim = Int2Tim(RightStr($tim, 6));
	return($tim);
}

# 時間を'hhmm'で取得
sub TimeInt{
	my $tim = LeftStr(_get_DateTimeInt(1), 4);
	return($tim);
}

# 日付時間を'yyy/mm/dd hh:mm'で取得
sub DateTimeStr{
	my $tim = _get_DateTimeInt(2);
	my $day = Int2Day(LeftStr($tim, 8));
	$day .= ' '.Int2Tim(MidStr($tim, 9, 4));
	return($day);
}

# 日付時間を'yyy/mm/dd hh:mm:ss'で取得
sub DateTimeSecStr{
	my $tim = _get_DateTimeInt(2);
	my $day = Int2Day(LeftStr($tim, 8));
	$day .= ' '. Int2Tim(RightStr($tim, 6));
	return($day);
}


;#//////////////////////////////////////////////////////////////////////////////
;# 日付判定関数
;# k2::Date Format = 'yyyy/mm/dd)' or 'yyyymmdd'
;#//////////////////////////////////////////////////////////////////////////////


;#------------------------------------------------------------------------------
;# 便利機能!!
;# 日付関数は基本的に引数には
;# 'yyy/mm/dd, yyymmdd' のどのタイプも使用可能
;#    ↑ Splitter は数字・エスケープ文字以外何でも良い
;# 取りあえず、toSeireki()を実行すれば、後は全ての関数を使用できる
;#
;# $ymd = Trim($ymd);
;# $ymd = toSeireki($ymd);
;#         :
;#     日付の計算
;#         :
;#------------------------------------------------------------------------------


# うるう年の判定
sub isLeapYear{
	my ($ymd) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my $ret = ($y%4000!=0 && ($y%400==0 || ($y%100!=0 && $y%4==0))) ? 1 : 0;
	return($ret);
}

# 未来日チェック
sub isFuture{
	my ($ymd) = @_;
	my $ret = 0;
	if(isDate($ymd)){
		$ret = 1 if(Day2Int($ymd) > DateInt());
	}
	return($ret);
}

# 日付フォーマット判定
# yyyymmdd or yyy/mm/dd かつ年月日が範囲内か判定
sub isDate{
	my ($ymd) = @_;
	my $ret = 0;

	$ymd = Day2Int($ymd);
	if(isNumeric($ymd) && (length($ymd) == 8)){
		my ($y, $m, $d) = Day2ymd($ymd);
		if($y >= 1900){
			if(($m >= 1) && ($m <= 12)){
				$ret = 1 if(($d >= 1) && ($d <= DaysInMonth($ymd)));
			}
		}
	}
	return($ret);
}

# 日付フォーマット判定
# '$ymd'はリファレンス
sub isDateFormat{
	my ($ymd) = @_;
	FixStr(\$$ymd);
	$$ymd = ngp2ymd($$ymd);
	$$ymd = ymd2fix($$ymd);
	$$ymd = toSeireki($$ymd);
	return(isDate($$ymd));
}


;#//////////////////////////////////////////////////////////////////////////////
;# 日付変換関数
;#//////////////////////////////////////////////////////////////////////////////


# 日付をymd要素に分解
# (yyy/mm//dd || yyyymmdd) -> @(yyy. mm, dd)
# 'Splitter' は数字・エスケープ文字以外の何でも良い
# 日付関数は必ずこの関数を通過するので'Splitter' は気にすることはない
sub Day2ymd{
	my ($ymd) = @_;
	$ymd = TrimA($ymd);

	if(isNumeric($ymd)){
		$ymd = Int2Day($ymd);
	}else{
		$ymd =~ s/[^\d]/\//g;
	}

	my @nm = (4, 2, 2);
	my @ret = CutOff('/', $ymd);
	for(my $i = 0; $i < @ret; $i++){
		$ret[$i] = RightStr('0000'.$ret[$i], $nm[$i]);
	}
	return(@ret);
}

# yyyy/m/d等からyyyy/mm/ddに変換
sub ymd2fix{
	my ($ymd) = @_;
	my $z = '0000';
	my ($y, $m, $d) = Day2ymd(TrimA($ymd));
	my $ret = RightStr($z.$y, 4).'/'.RightStr($z.$m, 2).'/'.RightStr($z.$d, 2);
	return($ret);
}

# 日付フォーマットを数値に変換
# yyy/mm/dd -> yyymmdd
sub Day2Int{
	my ($ymd) = @_;
	$ymd = ymd2fix($ymd);
	$ymd =~ s/\D//g;
	my $ret = $ymd;
	return($ret);
}

# 数値を日付フォーマットに変換
# yyymmdd -> yyy/mm/dd
sub Int2Day{
	my ($s) = @_;
	my $ret = join('/',LeftStr($s, 4),MidStr($s, 5, 2),RightStr($s, 2));
	return($ret);
}

# yyyy/mm/ddからyyyy年mm月dd日に変換
sub ymd2ngp{
	my ($ymd) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my $ret = $y.'年'.$m.'月'.$d.'日';
	return($ret);
}

# yyyy年mm月dd日からyyyy/mm/ddに変換
sub ngp2ymd{
	my ($ymd) = @_;
	$ymd =~ s/\D/\//g;
	do{
		$ymd =~ s/\/\//\//g;
	}while($ymd =~ /\/\//);
	$ymd =~ s/\/$//g;
	return($ymd);
}


#-------------------------------------------------------------------------------
# 和暦西暦変換
#-------------------------------------------------------------------------------


# 和暦変換用変数
my @DAY_WA_GG = ('明治','大正','昭和','平成');
my @DAY_WA_Y0 = (18681022,19120730,19261225,19890108);
my @DAY_WA_Y1 = (19120729,19261224,19890107,99991231);


# 西暦から和暦に変換
sub toWareki{
	my ($ymd) = @_;
	my $ret = '';

	$ymd = toSeireki($ymd) unless(isDate($ymd));
	$ymd = Day2Int($ymd);

	for(my $i = 0; $i <= @DAY_WA_GG; $i++ ){
		if(($ymd >= $DAY_WA_Y0[$i]) && ($ymd <= $DAY_WA_Y1[$i])){
			my ($y, $m, $d) = Day2ymd($ymd);
			$y -= LeftStr($DAY_WA_Y0[$i], 4) - 1;
			$ret = $DAY_WA_GG[$i].$y.'年'.$m.'月'.$d.'日';
			last;
		}
	}
	return($ret);
}

# 和暦から西暦に変換
# 元号yyyy年mm月dd日->yyyy/mm/dd
sub toSeireki{
	my ($ymd) = @_;
	my ($i, $p, $g, @ce, $ret);

	$ymd = cnv2sjis($ymd);
	$ymd = zen2han($ymd);
	$ymd = TrimA($ymd);

	unless(isDate($ymd)){
		for($i = 0; $i < @DAY_WA_GG; $i++){
			$p = PosStr($DAY_WA_GG[$i], $ymd);
			if($p == 1){
				$ymd = RightStrW($ymd, LengthW($ymd) - 2);
				$g = $i + 1;
				last;
			}
		}
		if($g){
			my @dm = (['年','月','日'], [4, 2, 2]);
			for($i = 0; $i <= 2; $i++){
				$p = PosStrW($dm[0][$i], $ymd);
				if($p){
					$ce[$i] = LeftStrW($ymd, $p - 1);
					$ymd = RightStrW($ymd, LengthW($ymd) - $p);
				}
			}
			if(isNumeric(Joint('', @ce))){
				$g--;
				$ce[0] = LeftStr($DAY_WA_Y0[$g], $dm[1][0]) + $ce[0] - 1;
				for(my $i = 0; $i <= 2; $i++){
					if(length($ce[$i]) <= $dm[1][$i]){
						$ce[$i] = RightStr('0000'.$ce[$i], $dm[1][$i]);
					}
				}
				$ymd = Joint('', @ce);
				if(isDate($ymd)){
					if( ($ymd >= $DAY_WA_Y0[$g]) && ($ymd <= $DAY_WA_Y1[$g]) ){
						$ret =  Joint('/', @ce);
					}
				}
			}
		}
	}else{
   	    $ret = ymd2fix($ymd);
	}
	return($ret);
}


;#//////////////////////////////////////////////////////////////////////////////
;# 日付計算関数
;#//////////////////////////////////////////////////////////////////////////////


# 年齢計算
# $day = '' は今日現在の年齢
# $day != '' は'$day'時点での年齢
sub Age{
	my ($ymd, $day) = @_;
	$day = DateInt()unless($day);
	$day = Day2Int($day);
	my $age = int(($day - Day2Int($ymd)) / 10000);
	return($age);
}

# 年の加減算
# '$n'は'+-'で計算
sub incYear{
	my ($ymd, $n) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my $ret = $y + $n.'/'.$m.'/'. $d;
	return($ret);
}

# 月の加減算
# '$n'は'+-'で計算
sub incMonth{
	my ($ymd, $n) = @_;

	my ($y, $m, $d) = Day2ymd($ymd);
	my $fg = ($d eq '') ? 1 : 0;
	$m = $m + $n;

	if($m < 1){
		$m = 12 - $m;
		$y -= 1;
	}
	if($m > 12){
		$m = $m - 12;
		$y += 1;
	}

	my $n = DaysInMonth("$y/$m/$d");
	$d = $n if($d > $n);

	my $ret = sprintf("%4d/%02d/%02d", $y, $m, $d);
	$ret = LeftStr($ret, 7)if($fg || RightStr($ret, 2) eq '00');

	return($ret);
}

# 日付の加減算($ymd±$n)
# 'yyyymmdd', '±dd'
# 'yyyy/mm/dd', '±dd'
sub incDay{
	my ($ymd, $n) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my $day = timelocal(0, 0, 0, $d, $m - 1, $y) + (24 * 60 * 60 * $n);
	my @tim = localtime($day);
	my $ret = sprintf("%4d/%02d/%02d", $tim[5] + 1900, $tim[4] + 1, $tim[3]);
	return($ret);
}

# 期間日数計算
# 日付は絶対値で計算($dy0 - $dy1)
sub SpanDays{
	my ($dy0, $dy1) = @_;
	my ($y0, $m0, $d0) = Day2ymd($dy0);
	my ($y1, $m1, $d1) = Day2ymd($dy1);
	my $dy0 = timelocal(0, 0, 0, $d0, $m0 - 1, $y0);
	my $dy1 = timelocal(0, 0, 0, $d1, $m1 - 1, $y1);
	my $ret = int(($dy0 - $dy1) / 60 / 60 / 24);
	return($ret);
}


;#//////////////////////////////////////////////////////////////////////////////
;# 日付要素取得関数
;#//////////////////////////////////////////////////////////////////////////////


# 英語の月名を取得
# '$ymd' が1〜2桁の場合月とみなす
sub EnglishMonth{
	my ($ymd) = @_;
	my ($y, $m, $d, $ret);
	my @MONTH = (
		'Jan','Feb','Mar','Apr','May','Jun',
		'Jul','Aug','Sep','Oct','Nov','Dec'
	);

	if(length($ymd) <= 2){
		$m = ( ($ymd >= 1) && ($ymd <= 12) ) ? $ymd : 0;
	}else{
		$ymd = ymd2fix($ymd);
		($y, $m, $d) = Day2ymd($ymd);
	}

	$ret = ($m > 0) ? $MONTH[$m - 1] : '';
	return($ret);
}

# 月の日数を取得
# (1月〜12月) -> (1〜12)
sub DaysInMonth{
	my ($ymd) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my @day = (31,28,31,30,31,30,31,31,30,31,30,31);
	if(isLeapYear($y)){ $day[1]++ }
	my $ret = $day[$m - 1];
	return($ret);
}

# 第何週目かを取得
# 1週目 = 1
sub Day2Weeks{
	my ($ymd) = @_;

	my $fdw = 0;
	my ($y, $m, $d) = Day2ymd($ymd);

	$fdw = DayOfWeekIndex($y . $m . '01') - 1;
	$fdw = $fdw + $d;
	$fdw = int(($fdw + 6) / 7);

	return($fdw);
}

# 曜日インデックスの取得
# (日〜土) -> (1〜7)
sub DayOfWeekIndex{
	my ($ymd) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);
	my $ret = (localtime(timelocal(0, 0, 0, $d, $m - 1, $y)))[6] + 1;
	return($ret);
}

# 曜日の取得
# 英語::$sw=1、日本語::$sw=2
sub DayOfWeek{
	my ($ymd, $sw) = @_;
	$ymd = ymd2fix($ymd);
	$sw = MinMax($sw, 1, 2);
	my @DOW = (
		['SUN','MON','TUE','WED','THU','FRI','SAT'],
		['日','月','火','水','木','金','土']
	);
	my $ret = $DOW[$sw - 1][DayOfWeekIndex($ymd) - 1];
	return($ret);
}


;#//////////////////////////////////////////////////////////////////////////////
;# 春分、秋分、休日、旧暦、干支関数
;#//////////////////////////////////////////////////////////////////////////////


# 春分の日・秋分の日の取得
# $ymd=yyyy/mm(/dd) or yyyymm(dd)
# $y(mm=3)d = 春分の日、$y(mm=9)d = 秋分の日
sub EquinoxDay{
	my ($ymd) = @_;
	my ($y, $m, $d) = Day2ymd($ymd);

	if($y >= 1980 && $y <= 2099){
		my $org = 1980;
		my $def = 0.242194 * ($y - $org) - int(($y - $org) / 4);

		if($m == 3){
			my $Equinox3 = int(20.8431 + $def);
			return($Equinox3);
		}

		if($m == 9){
			my $Equinox9 = int(23.2488 + $def);
			return($Equinox9);
		}
	}
	return('');
}

# 春分の日・秋分の日の判定
sub isEquinox{
	my ($ymd) = @_;
	$ymd = ymd2fix($ymd);
	my ($y, $m, $d) = Day2ymd($ymd);

	if($m == 3){
		my $Equinox3 = EquinoxDay(3);
		return(3)if($d == $Equinox3);
	}

	if($m == 9){
		my $Equinox9 = EquinoxDay(9);
		return(9)if($d == $Equinox9);
	}
    return(0);
}

# $y年$m月$n週目$w曜日の日付を得る
# このコーディングはダサい!!
# 何とかしよう!!
sub Factor2Day{
	my($y, $m, $n, $w)= @_;
	$y = RightStr('0000'.$y, 4);
	$m = RightStr('0000'.$m, 2);
	my ($ln, $ct, $ret) = (DaysInMonth($y.$m), 0, '');
	for(my $i = 1; $i <= $ln ;$i++){
		$ct++ if(DayOfWeekIndex($y.'/'.$m.'/'.$i) == $w);
		if($ct == $n){
			$ret = $m.RightStr('00'.$i, 2);
			$ct = 0;
			last;
		}
	}
	return($ret);
}

# 休日名の定義
# $y = 休日名を得たい年度
# @$hn = 祝日名(リファレンス)
# @$hd = 祝日日(リファレンス)
sub HolidayDef{
	my ($y, $hn, $hd) = @_;
	my ($seijn, $umihi, $keiro, $taiku);

	# 春分の日と秋分の日の定義
	my $eqnx3 = '03'.EquinoxDay($y.'03');
	my $eqnx9 = '09'.EquinoxDay($y.'09');

	# 成人の日(1月第2月曜)
	$seijn = Factor2Day($y, '01', 2, 2);

	# 体育の日(10月第2月曜)
	$taiku = Factor2Day($y, '10', 2, 2);

	if($y <= 2002){
		# 2002年以前は固定休日
		$umihi = '0720';
		$keiro = '0915';
	}else{
		# 海の日(7月第3月曜)
		$umihi = Factor2Day($y, '07', 3, 2);
		# 敬老の日(9月第3月曜)
		$keiro = Factor2Day($y, '09', 3, 2);
	}

	@$hn = (
		['0101', '元日'        ],
		[$seijn, '成人の日'    ],
		['0211', '建国記念の日'],
		[$eqnx3, '春分の日'    ],
		['0429', '昭和の日'    ],
		['0503', '憲法記念日'  ],
		['0504', 'みどりの日'  ],
		['0505', 'こどもの日'  ],
		[$umihi, '海の日'      ],
		[$keiro, '敬老の日'    ],
		[$eqnx9, '秋分の日'    ],
		[$taiku, '体育の日'    ],
		['1103', '文化の日'    ],
		['1123', '勤労感謝の日'],
		['1223', '天皇誕生日'  ]
	);

	# 固定休日の定義
	if($y <= 2002){
		@$hd = ('0101', '0211', $eqnx3, '0429', '0503', '0504', '0505',
				'0720', '0915', $eqnx9, '1103', '1123', '1223');
	}else{
		@$hd = ('0101', '0211', $eqnx3, '0429', '0503', '0504', '0505',
				$eqnx9, '1103', '1123', '1223');
	}
	return(1);
}

# 全ての祝日を返す
# $ymd=yyyy(該当年度、区切り子は',')
sub HolidayAll{
	my($ymd)= @_;
	$ymd = ymd2fix($ymd);
	my ($y, $m, $d) = Day2ymd($ymd);

	my (@ret, $day, $hd, $s, @hd, @hn);
	HolidayDef($y, \@hn);

	for(my $i = 0; $i < @hn; $i++){
		$day = $y.$hn[$i][0];
		$s = LeftStr($hn[$i][0], 2).'/'.RightStr($hn[$i][0], 2);
		push(@ret, $s.','.$hd)if(isHoliday($day, \$hd));
	}
	return(@ret);
}

# 国民の祝日の判定
# まだまだ無駄な処理が多い
# 春分の日・秋分の日は自動計算(1980-2099)
# 引数'$hdn'があると祝日名が返る(リファレンス)
# 返り値=(1:国民の祝日、2:振替休日、3:国民の休日)
sub isHoliday{
	my($ymd, $hdn)= @_;
	$ymd = ymd2fix($ymd);
	my ($y, $m, $d) = Day2ymd($ymd);
	my ($mm, $dy, @hd, @hn, %day, %dow, %d2w, %fgh, $eqnx3, $eqnx9);

	# 計算用日付要素定義 ///////////////////////////////////////////////////////
	my @def = (-2, -1, 0, 1);
	for(my $i = 0; $i < @def; $i++){
		my $comd = incDay($ymd, $def[$i]);
		$day{$def[$i]} = RightStr(Day2Int($comd), 4);
		$dow{$def[$i]} = DayOfWeekIndex($comd);
		$d2w{$def[$i]} = int(($d - 1) / 7) + 1;
		$fgh{$def[$i]} = 0;
	}
	#///////////////////////////////////////////////////////////////////////////

	# 休日名,春分の日,秋分の日の定義 ///////////////////////////////////////////
	HolidayDef($y, \@hn, \@hd);

	# 休日名
	$$hdn = '';
	for(my $i = 0; $i < @hn; $i++){
		if($hn[$i][0] eq $m.$d){
			$$hdn = $hn[$i][1];
			last;
		}
	}
	#///////////////////////////////////////////////////////////////////////////

	# 該当日 ///////////////////////////////////////////////////////////////////
	# 日曜チェック
	return(1)if($dow{0} == 1);
	# 固定休日チェック
	$dy = $day{0};
	return(1)if(grep(/^$dy$/, @hd));
	# 変動休日チェック
	return(1)if(isSpecial($y, $m, $dow{0}, $d2w{0}));
	#///////////////////////////////////////////////////////////////////////////

	# 1日前 ///////////////////////////////////////////////////////////////////
	# 固定休日チェック
	$dy = $day{-1};
	($fgh{-1} = 1)if(grep(/^$dy$/, @hd));
	# 変動休日チェック
	$mm = LeftStr($day{-1}, 2);
	($fgh{-1} = 1)if(isSpecial($y, $mm, $dow{-1}, $d2w{-1}));
	#///////////////////////////////////////////////////////////////////////////

	# 2日前 ///////////////////////////////////////////////////////////////////
	# 固定休日チェック
	$dy = $day{-2};
	($fgh{-2} = 1)if(grep(/^$dy$/, @hd));
	# 変動休日チェック
	$mm = LeftStr($day{-2}, 2);
	($fgh{-2} = 1)if(isSpecial($y, $mm, $dow{-2}, $d2w{-2}));
	#///////////////////////////////////////////////////////////////////////////

	# 振替休日 /////////////////////////////////////////////////////////////////
	# ハッピーマンデー
	# (1日前=日曜 && 1日前=休日)
	($fgh{0} = 1)if($fgh{-1} == 1 && $dow{-1} == 1);
	# 振替休日
	# (2日前=休日 && 1日前=休日)
	($fgh{0} = 1)if($fgh{-2} == 1 && $fgh{-1} == 1);
	# ハッピーマンデー or 振替休日
	if($fgh{0}){
		$$hdn = '振替休日' unless($$hdn);
		return(2);
	}
	#///////////////////////////////////////////////////////////////////////////

	# 1日後 ///////////////////////////////////////////////////////////////////
	# 固定休日チェック
	$dy = $day{1};
	($fgh{1} = 1)if(grep(/^$dy$/, @hd));
	# 変動休日チェック
	$mm = LeftStr($day{2}, 2);
	($fgh{1} = 1)if(isSpecial($y, $mm, $dow{1}, $d2w{1}));
	# 国民の休日
	# (1日前=祝日 && 1日後=祝日)
	if($fgh{-1} && $fgh{1}){
		$$hdn = '国民の休日' unless($$hdn);
		return(3);
	}
	#///////////////////////////////////////////////////////////////////////////

	# 休日以外
	return(0);

	#///////////////////////////////////////////////////////////////////////////
	# Local function
	# 変動休日の判定
	# '$mm月'の'$ws週目'の'$wd曜日'
	sub isSpecial{
		my ($yy, $mm, $ws, $wd) = @_;

		# 成人の日(1月第2月曜)
		return(1)if($mm == 1  && $ws == 2 && $wd == 2);
		# 体育の日(10月第2月曜)
		return(1)if($mm == 10 && $ws == 2 && $wd == 2);
		if($yy > 2002){
			# 海の日(7月第3月曜)
			return(1)if($mm == 7  && $ws == 3 && $wd == 2);
			# 敬老の日(9月第3月曜)
			return(1)if($mm == 9  && $ws == 3 && $wd == 2);
		}
		return(0);
	}
	#///////////////////////////////////////////////////////////////////////////
}

# 旧暦の月名を取得
# ($f=1)=>漢字、($f=2)=>ヨミ
sub Kyureki{
	my($m, $f)= @_;
	if(isDate($m)){
		my ($y, $s, $d) = Day2ymd($m);
		$m = $s;
	}
	my @om;
	$f = MinMax($f, 1, 2);
	if($f == 1){
		@om = ('睦月', '如月', '弥生', '卯月'  ,'皐月', '水無月',
				'文月', '葉月', '長月', '神無月','霜月', '師走');
	}else{
		@om = ('むつき','きさらぎ','やよい','うづき','さつき','みなづき',
				'ふみづき','はづき','ながつき','かんなづき','しもつき','しわす');
	}
	return($om[$m - 1]);
}


# 干支を得る
# 西暦を12で剰余すると'0=申'…'11=未'となる
# ($f = 1)=>漢字、($f = 2)=>ヨミ
# 1980 % 12 = 0 -> さる -> 28才
# 1968 % 12 = 0 -> さる -> 40才
sub Junishi{
	my($y, $f)= @_;
	my @eto;

	$f = MinMax($f, 1, 2);
	if($f == 1){
		@eto = ('申\','酉','戌','亥','子','丑','寅','卯','辰','巳','午','未');
	}else{
		@eto = ('さる','とり','いぬ','い','ね','うし','とら','う','たつ','み','うま','ひつじ');
	}

    # スクリプト中に直接記述すると文字化け又はエラーが発生する文字の考察
    #
    # {'申' = 'x905c(sjis)'}の{'x5c' = '\'}のせいで文字化けしてしまう
    # 因みに、この文字が文字列の最後に付いた時のみ発生すると思う!?
    # が、しかし、Trim('申 ')or'申\'でばっちり、こりゃ名案だ!!
    # 漢字2バイト目が'x5c'になるものは必ずこうしよう
    # ってことで、メモ φ(~_~;)
    #
    # 文字化けする文字一覧(罫線以外で)
    # ―ソЫ\噂浬欺圭構蚕十申曾箪貼能表暴予禄
    # ™\喀媾彌拿杤歃à\á\â\ã\ä\å\æ\ç\è\é\ê\úxûx
    #
    # 方法2種類
    # {$s = '\申';}、{$s = '申 '; $s = Trim($s);}
    #

    return($eto[$y % 12]);
}

## K2/LIB::PERL LIBRARY++ ------------------------------------------------------
1;                                                      ## Presented by Dr.k2 ##
## EOF -------------------------------------------------------------------------