PowerShellで1949年以降の休日を取得する
たしか先月で、GoogleのカレンダーAPI、v1/v2が使えなくなりました。
ということでGoogle依存を解消したPowerShellでの休日取得を考えてみました。
追記 2021/10/12
2021年東京オリンピック周りの変更を反映
2007以降のみを削除
関数名等修正
過去の記事と今回の方針
UWSCで祝日を算出する - じゅんじゅんのきまぐれ
UWSCで1949年以降の祝日を算出する - じゅんじゅんのきまぐれ
javascriptで休日判定 - じゅんじゅんのきまぐれ
と(PowerShellではないですが)書いてきました。
また、完全にハードコードしてしまえ、という思想の人もいるのですね。
holiday_jp(Ruby gem) のPHP版、JavaScript版を作りました - Copy/Cut/Paste/Hatena
これはこれでアリかと思います。
ハードコード版も作ってみましょうか。
オフライン版
完全ハードコードの人のと答え合わせしてあります。
function Get-HolidayJp() { Param ([int]$Year = [DateTime]::Now.Year) # 注意! 1948年以前と2100年以降は未対応 if($Year -le 1948 -or $Year -ge 2100) { return @() } # オブジェクト用意 $holidayObjs = @{ 元日=@{ name='元日'; nameEn='New Year''s Day' } 成人=@{ name='成人の日'; nameEn='Coming of Age Day' } 建国=@{ name='建国記念の日'; nameEn='National Foundation Day' } 春分=@{ name='春分の日'; nameEn='Vernal Equinox Day' } 憲法=@{ name='憲法記念日'; nameEn='Constitution Memorial Day' } みど=@{ name='みどりの日'; nameEn='Greenery Day' } 子供=@{ name='こどもの日'; nameEn='Children''s Day' } 海の=@{ name='海の日'; nameEn='Marine Day' } 山の=@{ name='山の日'; nameEn='Mountain Day' } 敬老=@{ name='敬老の日'; nameEn='Respect for the Aged Day' } 秋分=@{ name='秋分の日'; nameEn='Autumnal Equinox Day' } 体育=@{ name='体育の日'; nameEn='Health and Sports Day' } スポ=@{ name='スポーツの日'; nameEn='Health and Sports Day' } 文化=@{ name='文化の日'; nameEn='National Culture Day' } 勤労=@{ name='勤労感謝の日'; nameEn='Labor Thanksgiving Day' } 天皇=@{ name='天皇誕生日'; nameEn='Emperor''s Birthday' } 昭和=@{ name='昭和の日'; nameEn='Showa Day' } 振替=@{ name='振替休日'; nameEn='Holiday in lieu' } #国民=@{ name='国民の休日'; nameEn='Citizen''s Holiday' } オンラインにあわせる 国民=@{ name='休日'; nameEn='Holiday by law' } 明仁結婚=@{ name='皇太子明仁親王の結婚の儀'; nameEn='The Rite of Wedding of HIH Crown Prince Akihito' } 大喪=@{ name='昭和天皇の大喪の礼'; nameEn='The Funeral Ceremony of Emperor Showa.' } 即位=@{ name='即位礼正殿の儀'; nameEn='The Ceremony of the Enthronement of His Majesty th Emperor (at the Seiden)' } 徳仁結婚=@{ name='皇太子徳仁親王の結婚の儀'; nameEn='The Rite of Wedding of HIH Crown Prince Naruhito' } } # 特別組 $ret = New-Object System.Collections.SortedList if($Year -eq 1959) { $ret[[DateTime]"$Year/04/10"] = $holidayObjs['明仁結婚'] } if($Year -eq 1989) { $ret[[DateTime]"$Year/02/24"] = $holidayObjs['大喪'] } if($Year -eq 1990) { $ret[[DateTime]"$Year/11/12"] = $holidayObjs['即位'] } if($Year -eq 1993) { $ret[[DateTime]"$Year/06/09"] = $holidayObjs['徳仁結婚'] } if($Year -eq 2019) { $ret[[DateTime]"$Year/05/01"] = $holidayObjs['国民'] # 令和天皇の即位 $ret[[DateTime]"$Year/10/22"] = $holidayObjs['国民'] # 令和天皇の即位礼正殿の儀 } # 固定組 $ret[[DateTime]"$Year/01/01"] = $holidayObjs['元日'] $ret[[DateTime]"$Year/05/03"] = $holidayObjs['憲法'] # 憲法記念日 1948年から $ret[[DateTime]"$Year/05/05"] = $holidayObjs['子供'] $ret[[DateTime]"$Year/11/03"] = $holidayObjs['文化'] # 明治節 $ret[[DateTime]"$Year/11/23"] = $holidayObjs['勤労'] # 勤労感謝の日 新嘗祭1873年からか?。勤労感謝の日としては1948年から $ret[[DateTime]"$Year/04/29"] = $holidayObjs['天皇'] # 天皇誕生日 昭和。年が進むと名称が変わる if($Year -ge 1967) { $ret[[DateTime]"$Year/02/11"] = $holidayObjs['建国'] } # 建国記念の日 紀元節 if($Year -ge 1989) { if($Year -ge 2020) { $ret[[DateTime]"$Year/02/23"] = $holidayObjs['天皇'] # 令和 } elseif($Year -lt 2019) { $ret[[DateTime]"$Year/12/23"] = $holidayObjs['天皇'] # 平成 } if($Year -ge 2007) { $ret[[DateTime]"$Year/04/29"] = $holidayObjs['昭和'] $ret[[DateTime]"$Year/05/04"] = $holidayObjs['みど'] } else { $ret[[DateTime]"$Year/04/29"] = $holidayObjs['みど'] } } if($Year -ge 2016 -and $Year -ne 2020 -and $Year -ne 2021) { $ret[[DateTime]"$Year/08/11"] = $holidayObjs['山の'] } # 第n月曜組 $getNthDay = { Param([int]$n, [DayOfWeek]$w, [DateTime]$b = [DateTime]::Now) $d = 1 - $b.Day $c = [int]$w - [int]($b.AddDays($d).DayOfWeek) $d += $c + ([int]($c -lt 0) + $n - 1) * 7 return $b.AddDays($d) } if($Year -ge 2000) { $ret[(&$getNthDay 2 Monday "$Year/01/15")] = $holidayObjs['成人'] if($Year -ge 2003) { $ret[(&$getNthDay 3 Monday "$Year/09/15")] = $holidayObjs['敬老'] if($Year -eq 2020) { $ret[[DateTime]"$Year/07/23"] = $holidayObjs['海の'] $ret[[DateTime]"$Year/07/24"] = $holidayObjs['スポ'] $ret[[DateTime]"$Year/08/10"] = $holidayObjs['山の'] } elseif($Year -eq 2021) { $ret[[DateTime]"$Year/07/22"] = $holidayObjs['海の'] $ret[[DateTime]"$Year/07/23"] = $holidayObjs['スポ'] $ret[[DateTime]"$Year/08/08"] = $holidayObjs['山の'] } else { $ret[(&$getNthDay 3 Monday "$Year/07/20")] = $holidayObjs['海の'] if($Year -ge 2021) { $ret[(&$getNthDay 2 Monday "$Year/10/10")] = $holidayObjs['スポ'] } else { $ret[(&$getNthDay 2 Monday "$Year/10/10")] = $holidayObjs['体育'] } } } else { $ret[[DateTime]"$Year/07/20"] = $holidayObjs['海の'] $ret[[DateTime]"$Year/09/15"] = $holidayObjs['敬老'] $ret[(&$getNthDay 2 Monday "$Year/10/10")] = $holidayObjs['体育'] } } else { if($Year -ge 1949) { $ret[[DateTime]"$Year/01/15"] = $holidayObjs['成人'] } if($Year -ge 1966) { $ret[[DateTime]"$Year/09/15"] = $holidayObjs['敬老'] $ret[[DateTime]"$Year/10/10"] = $holidayObjs['体育'] if($Year -ge 1996) { $ret[[DateTime]"$Year/07/20"] = $holidayObjs['海の'] } } } # 春分の日・秋分の日(1918-2099用) 1948年の秋分の日が最初の祝日 $ret[[DateTime]"$Year/03/$([Math]::Floor(22-(3-(($Year-1892)%4)+[Math]::Floor(($year-1892)/33))*0.25))"] = $holidayObjs['春分'] $ret[[DateTime]"$Year/09/$([Math]::Floor(25-(3-(($Year-1820)%4)+[Math]::Floor(($year-1820)/32))*0.25))"] = $holidayObjs['秋分'] # 振替休日 1973年から(ただし、1973-02-11は除く) if($Year -ge 1973) { $i = 0 while($i -lt $ret.Count) { $t = $ret.GetKey($i) if($t -gt [DateTime]'1973/02/11') { if($t.DayOfWeek -eq 'Sunday') { while($ret.ContainsKey($t)) { $t =$t.AddDays(1) } $ret[$t] = $holidayObjs['振替'] $i++ } } $i++ } } # 国民の休日 1986年から if($Year -gt 1985) { $i = 1 while($i -lt $ret.Count) { $t = $ret.GetKey($i-1).AddDays(1) if($t -eq $ret.GetKey($i).AddDays(-1) -and $t.DayOfWeek -ne 'Sunday') { $ret[$t] = $holidayObjs['国民'] $i++ } $i++ } } return $ret }
テストコード(Get-HolidayHardCodeにも依存)
& { for($i = 1970; $i -lt 2051; $i++) { $resOff = Get-HolidayJp $i $resHar = Get-HolidayHardCode $i if($resOff.Count -ge $resHar.Count) { for($j = 0; $j -lt $resOff.Count; $j++) { $t = $resOff.GetKey($j) if($resOff[$t].nameEn -ne $resHar[$t].nameEn -or $resOff[$t].name -ne $resHar[$t].name) { '内容が違う Offline:{0:yyyy/MM/dd} {1} {2} HardCode:{3} {4}' -f $t,$resOff[$t].nameEn,$resOff[$t].name,$resHar[$t].nameEn,$resHar[$t].name } } } else { for($j = 0; $j -lt $resHar.Count; $j++) { $t = $resHar.GetKey($j) if($resOff[$t].nameEn -ne $resHar[$t].nameEn -or $resOff[$t].name -ne $resHar[$t].name) { '内容が違う Offline:{0:yyyy/MM/dd} {1} {2} HardCode:{3} {4}' -f $t,$resOff[$t].nameEn,$resOff[$t].name,$resHar[$t].nameEn,$resHar[$t].name } } } } }
ハードコード版
holidays.ymlを読み込み式にしました。
gitから取得して適宜パスを修正してください。
https://github.com/holiday-jp/holiday_jp
function Get-HolidayHardCodeAll() { # オブジェクト用意 $holidayObjs = @{ 元日=@{ name='元日'; nameEn='New Year''s Day' }; 成人の日=@{ name='成人の日'; nameEn='Coming of Age Day' }; 建国記念の日=@{ name='建国記念の日'; nameEn='National Foundation Day' }; 春分の日=@{ name='春分の日'; nameEn='Vernal Equinox Day' }; 憲法記念日=@{ name='憲法記念日'; nameEn='Constitution Memorial Day' }; みどりの日=@{ name='みどりの日'; nameEn='Greenery Day' }; こどもの日=@{ name='こどもの日'; nameEn='Children''s Day' }; 海の日=@{ name='海の日'; nameEn='Marine Day' }; 山の日=@{ name='山の日'; nameEn='Mountain Day' }; 敬老の日=@{ name='敬老の日'; nameEn='Respect for the Aged Day' }; 秋分の日=@{ name='秋分の日'; nameEn='Autumnal Equinox Day' }; 体育の日=@{ name='体育の日'; nameEn='Health and Sports Day' }; スポーツの日=@{ name='スポーツの日'; nameEn='Health and Sports Day' }; 文化の日=@{ name='文化の日'; nameEn='National Culture Day' }; 勤労感謝の日=@{ name='勤労感謝の日'; nameEn='Labor Thanksgiving Day' }; 天皇誕生日=@{ name='天皇誕生日'; nameEn='Emperor''s Birthday' }; 昭和の日=@{ name='昭和の日'; nameEn='Showa Day' }; 振替休日=@{ name='振替休日'; nameEn='Holiday in lieu' }; #国民の休日=@{ name='国民の休日'; nameEn='Citizen''s Holiday' } オンラインにあわせる 休日=@{ name='休日'; nameEn='Holiday by law' }; 大喪の礼=@{ name='昭和天皇の大喪の礼'; nameEn='The Funeral Ceremony of Emperor Showa.' }; 即位礼正殿の儀=@{ name='即位礼正殿の儀'; nameEn='The Ceremony of the Enthronement of His Majesty th Emperor (at the Seiden)' }; 結婚の儀=@{ name='皇太子徳仁親王の結婚の儀'; nameEn='The Rite of Wedding of HIH Crown Prince Naruhito' }; } $ret = @{} $data = (Get-Content ../../holiday_jp/holidays.yml -Encoding UTF8) $data.Split("`n") | % { $tmp = $_ -replace '(.*)','' $tmp = $tmp -split ':' if($tmp.Length -gt 1) { $wk = $tmp[1].Trim() -split ' ' if($wk.Length -gt 1) { $tmp[1] = $wk[1] } $ret[[DateTime]$tmp[0]] = $holidayObjs[$tmp[1].Trim()] } } return $ret } function Get-HolidayHardCode() { Param ([int]$Year = [DateTime]::Now.Year) # 注意! 1970年より前と2051年以降は未対応 if($Year -lt 1970 -or $Year -ge 2051) { return @() } $ret = New-Object System.Collections.SortedList $res = Get-HolidayHardCodeAll foreach($t in $res.Keys) { if($t.Year -eq $Year) { $ret[$t] = $res[$t] } else { continue } } return $ret }