LoginSignup
7
7

More than 3 years have passed since last update.

日本の祝日を判定するPowerShellを書いた件

Last updated at Posted at 2019-12-06

Advent Calendar 初参加です。
Calendar にかけて、前回書いた記事「日本の祝日を判定するBashスクリプトを書いた件」を PowerShell で焼き直してみました。

日本の祝日情報をどこから貰うか

Bash版同様、内閣府のホームページから持ってきます。
Invoke-WebRequestcurlに相当するコマンドレットですが、PowerShellの入出力はすべて .NET のクラスオブジェクトなので、画面で確認するなら次のようになります。

取得方法
(Invoke-WebRequest https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv).Content
実行結果
国民の祝日・休日月日,国民の祝日・休日名称
1955/1/1,元日
1955/1/15,成人の日
1955/3/21,春分の日
1955/4/29,天皇誕生日
     :
2020/7/24,スポーツの日
2020/8/10,山の日
2020/9/21,敬老の日
2020/9/22,秋分の日
2020/11/3,文化の日
2020/11/23,勤労感謝の日

PowerShellスクリプト

仕様はBash版を踏襲しています。つまり、祝日ファイルをローカルにキャッシュし、古くなったら内閣府のサーバから取り直します。
確実に祝日と言える場合のみ、終了ステータスに 0 がセットされる点も同様です。
Bash版と比べてみると、言語の特徴が見えて面白いかもしれません。

check_holiday.ps1
###############################################################
#   本邦休日判定スクリプト
#   @author  MindWood
#   @param   チェック日付を yyyymmdd で指定。省略すると今日を仮定
#   @return  0       ... 確実に祝日
#            1       ... おそらく平日
#            上記以外 ... エラー
###############################################################

# 引数チェック
Param($DateStr = (Get-Date).ToString('yyyyMMdd'))
try {
    $CheckDate = [DateTime]::ParseExact($DateStr, 'yyyyMMdd', $null)
} catch {
    echo 'Invalid argument'
    exit 255
}
$CachePath = 'C:\tmp'                             # 内閣府提供の祝日ファイルをキャッシュするディレクトリ
$HolidayFile = Join-Path $CachePath holiday.csv   # 祝日登録ファイル名
$Limit = (Get-Date).AddMonths(-3)                 # 3ヶ月以上前は古い祝日登録ファイルとする

# 祝日登録ファイルが無い、もしくは祝日登録ファイルの更新日が古くなった場合、再取得する
if (! (Test-Path $HolidayFile) -or $Limit -gt (Get-ItemProperty $HolidayFile).LastWriteTime) {
    try {
        Invoke-WebRequest https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv -OutFile $HolidayFile
    } catch {
        echo $_.Exception.Message
        exit 250
    }
}

# 祝日として登録されていれば 0 を返却して終了(※祝日情報はyyyy/M/d形式で返る)
if (Select-String -Quiet ((Get-Date $CheckDate).ToString('yyyy/M/d') + ',') $HolidayFile) {
    exit 0
}

# 土日なら 0 を返却して終了
$DayOfWeek = (Get-Date $CheckDate).DayOfWeek
if ($DayOfWeek -in @('Saturday', 'Sunday')) {
    exit 0
}

# 年末年始(12月31日~1月3日)なら 0 を返却して終了
$MMDD = (Get-Date $CheckDate).ToString('MMdd')
if ($MMDD -eq '1231' -or $MMDD -le '0103') {
    exit 0
} 

# 上記いずれでもなければ平日として終了
exit 1

このスクリプトで、2019年12月26日から2020年1月16日までの平日を表示させると、次のようになります。

for ($date = '20191226'; $date -lt '20200116'; $date = [DateTime]::ParseExact($date, 'yyyyMMdd', $null).AddDays(1).ToString('yyyyMMdd')) {
    .\check_holiday.ps1 $date
    if (! $?) {
        echo "$date は恐らく平日です"
    }
}
20191226 は恐らく平日です
20191227 は恐らく平日です
20191230 は恐らく平日です
20200106 は恐らく平日です
20200107 は恐らく平日です
20200108 は恐らく平日です
20200109 は恐らく平日です
20200110 は恐らく平日です
20200114 は恐らく平日です
20200115 は恐らく平日です

なお、PowerShellでも $? で直前のコマンド終了ステータスを取得できますが、成功したか(0:True)失敗したか(0以外:False)のブール値で返るので注意が必要。失敗した理由まで知るには$LastExitCodeを評価すると良いです。

平日に必ず実行させるジョブがある場合、Falseかどうかだけ見れば良いことになります。

7
7
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7