こんにちは。阿部です。
みなさん、プレミアムフライデーしてますか?
私は、プレミアムフライデーかどうかにかかわらず、好きな日に休みを取りたい派ですが、それはさておき、プレミアムフライデーかどうか判定するバッチです。ご査収ください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
@echo off
rem 引数として年、月、日を受け取ります。
set y=%1
set m=%2
set d=%3
rem うるう年かどうか判定
set /a leap="((!(y%%4))&(!!(y%%100)))|!(y%%400)"
rem 月の日数を計算
set /a daysinmonth="(!(m-1)|!(m-3)|!(m-5)|!(m-7)|!(m-8)|!(m-10)|!(m-12))*31"
set /a daysinmonth+="(!(m-4)|!(m-6)|!(m-9)|!(m-11))*30"
set /a daysinmonth+="(!(m-2))*(28+leap)"
set /a remainingdays="daysinmonth-d"
rem ツェラーの公式で曜日を取得
set /a y="y-(!(m-1)|!(m-2))"
set /a m="m+(!(m-1)|!(m-2))*12"
set /a c="y/100,y=y%%100,g=5*c+(c/4)"
set /a dayofweek="(((d+(26*(m+1)/10)+y+(y/4)+(g))+5)%%7)+1"
rem 月末まで7日未満の金曜日かどうか
if %remainingdays% lss 7 (
if %dayofweek% equ 5 (
echo %1/%2/%3はプレミアムフライデーです。
goto :end
)
)
echo %1/%2/%3はプレミアムフライデーではありません。
:end
|
1
2
3
|
実行結果
IsPremiumFriday.bat 2019 2 22
2019/2/22はプレミアムフライデーです。
|
解説
Windowsには、日付計算を行うコマンドはありませんが、SET /A
コマンドで、数値計算を行うことができるので、これを利用して頑張って計算していきます。
うるう年かどうか判定する
まずは、うるう年判定です。年が((4の倍数である かつ 100の倍数でない) または 400の倍数である)場合、うるう年です。うるう年の場合、leap
は1、平年の場合は0が入ります。
!
演算子を利用すると、0が1に、0以外が1に変換されます。これを利用すると、「xがyの倍数である」を!(x%%y)
と表すことができます。
月の日数を求める
「にしむくさむらい」です。知らない人は調べてみてね。計算式がわかりにくいですが、例えば3月の場合、!(m-3)
の部分が1となり、その他の!(m-4)
などがすべて0となることで、3月の日数を得ています。また、2月の日数は、うるう年と平年で異なるので、先ほど求めたleap
を利用しています。
1
2
3
4
5
6
7
8
|
例えば3月の場合、次のように計算される。
daysinmonth=(!(m-1)|!(m-3)|!(m-5)|!(m-7)|!(m-8)|!(m-10)|!(m-12))*31
↓
daysinmonth=(!(3-1)|!(3-3)|!(3-5)|!(3-7)|!(3-8)|!(3-10)|!(3-12))*31
↓
daysinmonth=( 0| 1| 0| 0| 0| 0| 0)*31
↓
daysinmonth=31
|
曜日を求める
年月日の数値から曜日を計算するには、ツェラーの公式を使用します。
ただし、1月を13月、2月を14月として計算することに注意が必要です。
数式は、複雑そうに見えるかもしれませんが、SET /A
の計算が、もともと小数点以下切り捨てなので、床関数は無視できます。
また、2017年以降を考えれば良いので、グレゴリオ暦とユリウス暦の分岐も不要です。そうすると、
1
2
3
4
5
|
// ツェラーの公式簡易版(これで十分)
D = ((d + 26 * (m + 1) / 10 + Y + (Y / 4) + Γ + 5) % 7) + 1
Γ = 5 * c + (c / 4)
c = y / 100
Y = y % 100
|
結果は、月曜〜日曜が、D=1〜7の数値で得られます。
判定
ここまで準備できれば後は簡単です。プレミアムフライデーは月末の金曜日。つまり、月末から7日以内の金曜日のことです。
応用編
年、月からプレミアムフライデーの日を求めます。
最後の方を、ちょっと変えるだけです。月末日から(dayofweek+2) % 7
を引けば、曜日が調整されて直近の金曜日になるので、それがプレミアムフライデーです。
1
2
3
4
5
6
7
|
…
途中まで同じなので省略
…
set /a dayofweek="(((daysinmonth+(26*(m+1)/10)+y+(y/4)+(g))+5)%%7)+1"
rem 直近の金曜日を求める
set /a d="daysinmonth-(dayofweek+2)%%7"
echo %1/%2/%d%
|
1
2
3
|
実行結果
GetPremiumFriday.bat 2019 3
2019/3/29
|