Update:2017/04/28-01:39:00
2つの日付から日数を求める処理は比較的簡単ですが、特定の日付や曜日を除いた日数計算は多少複雑なものとなります。
休日や曜日を除外するには除外する日の指定方法を工夫する必要があります。
ここでは、除外する日を曜日「w0〜w6」、週数曜日「m週数曜日」、月の日付「d日付」、月日「y月日」のように
指定して該当する日付かどうかチェックします。
Windows 2000、XPで使えるようになったバッチ引数や環境変数の拡張機能を利用して処理のパターン化を行います。
たいした処理はしていませんが、何かの参考や役に立てば幸いです。
※Windows 9x/meでは利用できません。ご了承ください。
@title 営業日数計算
@echo off
PUSHD %~dp0
rem ===== 休日設定 ============================================================
rem 曜日設定 0..6 -> 日〜土 w9はダミーの曜日設定
set wday=w0 w6 w9
rem 日数での設定 d日数 日数:01〜31
set dday=d99
rem 週数曜日での設定 m週曜日曜数 m21→2週目の月曜日
set mday=m99
rem 月日設定 y0101・・y1231 1月1日〜12月31日
set yday=y0101 y0211 y0321 y0429 y0503 y0504 y0505 y0923 y1103 y1123 y1223 y9999
rem 月週曜日での設定 h0730->7月3週目日曜、h1025->10月2週目金曜 、h9999->ダミー設定
set hday=h0121 h0731 h0921 h1021 h9999
rem 例外日(休業日を営業日に振り替え) e1103->11月3日
set eday=e0402 e9999
rem ===== 処理設定 ============================================================
rem 振替休日 あり:1、なし:0
rem (wdayに設定した休業日とほかの休業日が重なった場合は翌日を振替休日とします。)
set /a f_sw = 1
rem 検査日付の表示(チェックした日付を表示します。)
set /a dsp_sw = 1
rem ==== 処理開始 =============================================================
rem 曜日の設定
set wd[0]=日
set wd[1]=月
set wd[2]=火
set wd[3]=水
set wd[4]=木
set wd[5]=金
set wd[6]=土
rem 月日数の設定
set /a md[0]=0
set /a md[1]=31
set /a md[2]=28
set /a md[3]=31
set /a md[4]=30
set /a md[5]=31
set /a md[6]=30
set /a md[7]=31
set /a md[8]=31
set /a md[9]=30
set /a md[10]=31
set /a md[11]=30
set /a md[12]=31
rem 年間の通算日数を計算
set /a yd[0]=0
for /L %%L in (1, 1, 12) do call :yd %%L
rem 開始日と終了日を設定(yyyy-mm-dd、yyyy.mm.dd も可)
set /p s=開始日(yyyy/mm/dd):
set /p e=終了日(yyyy/mm/dd):
if %s% GTR %e% call :swap
call :getdate %s%
set /a sy=%y% & set /a sm=%m% & set /a sd=%d%
call :getdate %e%
set /a ey=%y% & set /a em=%m% & set /a ed=%d%
rem 開始日付のエラーチェック
if %sy% LSS 2001 goto :OutOfRange lss-sy
if %sy% GTR 2100 goto :OutOfRange gtr-sy
call :uruu %sy%
if %sm% LSS 1 goto :OutOfRange lss-sm
if %sm% GTR 12 goto :OutOfRange gtr-sm
call set /a md = %%md[%sm%]%%
if %sm% EQU 2 set /a md+=%uruu%
if %sd% LSS 1 goto :OutOfRange lss-sd
if %sd% GTR %md% goto :OutOfRange gtr-sd
rem 終了日付のエラーチェック
if %ey% LSS 2001 goto :OutOfRange lss-ey
if %ey% GTR 2100 goto :OutOfRange gtr-ey
call :uruu %ey%
if %em% LSS 1 goto :OutOfRange lss-em
if %em% GTR 12 goto :OutOfRange gtr-em
call set /a md = %%md[%em%]%%
if %em% EQU 2 set /a md+=%uruu%
if %ed% LSS 1 goto :OutOfRange lss-ed
if %ed% GTR %md% goto :OutOfRange gtr-ed
call :days %sy% %sm% %sd%
set /a sdate=%days%
rem echo %sdate%
call :days %ey% %em% %ed%
set /a edate=%days%
rem echo %edate%
set /a flg = 0
set /a h = 0
set /a j = 0
if %f_sw% EQU 1 call :before
for /L %%L in (%sdate%, 1, %edate%) do call :holydaycheck %%L
echo.
set /a days = %edate% - %sdate% + 1
echo 調査日数=%days% , 営業日数=%j% , 休業日数=%h%
pause
POPD
exit /b
rem === ここからサブルーチン ==================================================
rem 引数ので与えられた日(西暦1年1月1日からの通算日数)が休日かどうかを調べます。
:holydaycheck
set /a fuldays = %1
rem 693961 -> 1900/12/31=1901/01/00
rem 10000倍することで、1年の日数を365.2425→3652425で表します。(小数点を外します。)
set /a days = (%fuldays% - 693961) * 10000
set /a y = %days% / 3652425
set /a year = %y% + 1901
rem 引数で与えられた日付の曜日を求めます。(0→日、1→月、2→火〜6→土)
set /a w = %fuldays% %% 7
rem 閏年のチェックを行います。
set /a uruu = 0
call :uruu %year%
set /a d = (%days% / 10000) - ((%y% * 3652425) / 10000)
rem 年初(1月1日)から各月の朔日(1日:ついたち)までの経過日数を使い月数を求めます。
set /a m = 12
:loop
rem 月数が2月以下なら閏日は算入しません。(0日とする)
if %m% LEQ 2 set /a uruu = 0
call set /a yd = %%yd[%m%]%% + %uruu%
if %d% GTR %yd% goto :exit-loop
set /a m -= 1
goto :loop
:exit-loop
rem m月d日を求めます。
set /a d = %d% - %yd%
rem dの日数を2桁表示でddに設定します。
set /a dd = %d% + 100
set dd=%dd:~-2%
rem mの月数を2桁表示でmmに設定します。
set /a mm = %m% + 100
set mm=%mm:~-2%
rem ymdwに年月日[曜日]を設定します。
call set ymdw=%year%/%mm%/%dd%_%%wd[%w%]%%_
rem 休日チェックのデータを作ります。(week:週数、mw:週数曜日、yd:月日、hd:月数週数曜日)
set /a week=(%d% - %w% + 6) / 7
set mw=%week%%w%
set yd=%mm%%dd%
set hd=%mm%%mw%
set ed=%yd%
rem 休日のチェックリストとなる文字列を作成します。
set wdd=%wday%
set ddd=%dday%
set mdd=%mday%
set ydd=%yday%
set hdd=%hday%
set edd=%eday%
rem 曜日での休業日であることを示すフラグをリセットしておきます。
set /a wflg = 0
rem チェック対象の曜日が曜日のリストにあれば、削除します。
call set wdd=%%wdd:w%w%=%%
rem 曜日のチェック文字列と休業日のリスト文字列が一致しなければ、休業日とします。
if not "%wdd%" == "%wday%" set /a flg=1 & set /a wflg=1
rem 日数で休業日のチェックを行います。
call set ddd=%%ddd:d%dd%=%%
if not "%ddd%" == "%dday%" set /a flg = %wflg% + 1
rem 週数と曜日で休業日のチェックを行います。
call set mdd=%%mdd:m%mw%=%%
if not "%mdd%" == "%mday%" set /a flg = %wflg% + 1
rem 月日で休業日のチェックを行います。
call set ydd=%%ydd:y%yd%=%%
if not "%ydd%" == "%yday%" set /a flg = %wflg% + 1
rem 月と週数と曜日で休業日のチェックを行います。
call set hdd=%%hdd:h%hd%=%%
if not "%hdd%" == "%hday%" set /a flg = %wflg% + 1
rem 月日で休業日としない(営業日となる)例外日のチェックを行います。
call set edd=%%edd:e%ed%=%%
if not "%edd%" == "%eday%" set /a flg = 0
rem 0 < flg ならば休業日に1を加え、違っていれば(0 = flg)営業日に1を加える。
if %flg% GTR 0 (set /a h+=1) else (set /a j+=1)
rem 0 < flg ならばh_flgを休に、違っていれば(0 = flg)h_flgを_にセットする。
if %flg% GTR 0 (set h_flg=休) else (set h_flg=_)
rem 0 < dsp_sw ならば日付と"休"または"_"(=営業日)を表示する。
if %dsp_sw% GTR 0 set /p dmy=%ymdw%[%h_flg%] < NUL
rem 1 < flg ならflgを1(振替休日の候補)に、違っていればflgを0にセットする。
if %flg% GTR 1 (set /a flg=1) else (set /a flg=0)
rem 0 = f_sw ならflgを0にセットする。(振替休日を使わない)
if %f_sw% EQU 0 set /a flg=0
exit /b
rem -------------------------------------------------------------------
rem 開始日の前日が休業日であるかチェックする。>
:before
set days = (%sdate% - 693961) * 10000
set /a y = (%days% - 10000) / 3652425
set /a year = %y% + 1901
set /a w = (%sdate% - 1) %% 7
set /a uruu = 0
call :uruu %year%
set /a d = (%days% / 10000) - ((%y% * 3652425) / 10000)
set /a m = 12
:loop_01
if %m% LEQ 2 set /a uruu = 0
call set /a yd = %%yd[%m%]%% + %uruu%
if %d% GTR %yd% goto :exit-loop_01
set /a m -= 1
goto :loop_01
:exit-loop_01
set /a d = %d% - %yd%
set /a dd = %d% + 100
set dd=%dd:~-2%
set /a mm = %m% + 100
set mm=%mm:~-2%
set /a week=(%d% - %w% + 6) / 7
set mw=%week%%w%
set yd=%mm%%dd%
set hd=%mm%%mw%
set ed=%yd%
set wdd=%wday%
set mdd=%mday%
set ydd=%yday%
set hdd=%hday%
set edd=%eday%
set /a wflg=0
if not "%wdd%" == "%wday%" set /a wflg = 1
call set mdd=%%mdd:m%mw%=%%
if not "%mdd%" == "%mday%" set /a flg = %wflg%
call set ydd=%%ydd:y%yd%=%%
if not "%ydd%" == "%yday%" set /a flg = %wflg%
call set hdd=%%hdd:h%hd%=%%
if not "%hdd%" == "%hday%" set /a flg = %wflg%
call set edd=%%edd:e%ed%=%%
if not "%edd%" == "%eday%" set /a flg = 0
if %f_sw% EQU 0 set /a flg=0
exit /b
rem -------------------------------------------------------------------
rem 西暦年、月、日から西暦元年(1年)1月1日(=1日)からの通算日数を求めます。
:days
set /a y = %1-1
set /a m = %2
set /a d = %3
set /a days = %y% * 365 + (%y% / 4) - (%y% / 100) + (%y% / 400)
call set /a days += %%yd[%m%]%%
set /a days += %d%
set /a uruu = 0
if %m% GTR 2 call :uruu %1
set days += %uruu%
exit /b
rem -------------------------------------------------------------------
rem 日付(yyyy/mm/dd)をy年(yyyy)、m月(mm)、d日(dd)に分解します。
:getdate
set dt=%~1
set dt=%dt:/= %
set dt=%dt:-= %
set dt=%dt:.= %
for /f "tokens=1-3" %%I in ("%dt%") do set y=%%I&set m=%%J&set d=%%K
exit /b
rem -------------------------------------------------------------------
rem 環境変数eとsの内容を入れ替えます。
:swap
set w=%e%
set e=%s%
set s=%w%
exit /b
rem -------------------------------------------------------------------
rem 1年の中で各月の1日までに経過している日数(=前月の末日までの日数)を求めます。
:yd
set /a b=%1-1
call set /a yd[%1] = %%yd[%b%]%% + %%md[%b%]%%
exit /b
rem -------------------------------------------------------------------
rem 閏年のチェックを行い、閏年であればuruuを1に、閏年でなければuruuを0にセットします。
:uruu
set /a u = %1
set /a r4 = u%%4
set /a r100 = u%%100
set /a r400 = u%%400
set uruu=0
if %r4% EQU 0 set uruu=1
if %r100% EQU 0 set uruu=0
if %r400% EQU 0 set uruu=1
exit /b
rem -------------------------------------------------------------------
rem エラーメッセージを表示します。
:OutOfRange
if "%1" == "lss-sy" echo 開始年は2001年以上2100年以下で設定してください。 & goto :EOF
if "%1" == "gtr-sy" echo 開始年は2001年以上2100年以下で設定してください。 & goto :EOF
if "%1" == "lss-sm" echo 開始月は1以上12以下で設定してください。 & goto :EOF
if "%1" == "gtr-sm" echo 開始月は1以上12以下で設定してください。 & goto :EOF
if "%1" == "lss-sd" call echo 開始日は1以上%%md[%sm%]%%以下で設定してください。 & goto :EOF
if "%1" == "gtr-sd" call echo 開始日は1以上%%md[%sm%]%%以下で設定してください。 & goto :EOF
if "%1" == "lss-ey" echo 終了年は2001年以上2100年以下で設定してください。 & goto :EOF
if "%1" == "gtr-ey" echo 終了年は2001年以上2100年以下で設定してください。 & goto :EOF
if "%1" == "lss-em" echo 終了月は1以上12以下で設定してください。 & goto :EOF
if "%1" == "gtr-em" echo 終了月は1以上12以下で設定してください。 & goto :EOF
if "%1" == "lss-ed" call echo 終了日は1以上%%md[%em%]%%以下で設定してください。 & goto :EOF
if "%1" == "gtr-ed" call echo 終了日は1以上%%md[%em%]%%以下で設定してください。 & goto :EOF
goto :EOF
連絡先:お問い合わせフォーム