-- Page 5 --
VBAおよびVB用の祝日判定用マクロ[関数](『kt関数アドイン/kt祝日名取得』の
ロジックと同じものです)を公開しています。また、VBA用の祝日判定用マクロ[関数]を
基にして、他言語向けに編集移植したコードを頂きましたので、併せて、このページで
公開します。
なお、祝日に関する詳細情報はこちらのページをご覧下さい。
VBA用コードは純粋にVB構文だけ(エクセル独自の機能は使ってません)で作って
ありますので、エクセルだけでなくアクセスや、その他のVBAを使うアプリケーション
でも利用できます。自由に各自のプログラムに組み込んで利用して下さい。なお、フリー/シェアソフト
※ 重要 ※
・ [ 東京五輪 祝日移動(2021年) ] (2020/11/28)
東京五輪特措法により2021年の「海の日/山の日/スポーツの日」が移動となります。
※ 訂正案内 2021/6/13 ※
Ruby および Apollo で 2020/2021年の「山の日」判定に誤りがありましたので修正しました。
修正箇所の説明は各言語版の項に記してあります。
※VBA以外に移植したコードも紹介しています※
・ 「東京五輪 祝日移動(2021年)」 改正への対応済みです。 (2020/11/28)
[ 旧サイト ( DIONサーバー ) の Internet Archive ( Page 5 ) ]
-頁- ・ 祝日判定マクロ の 設計方針について
・ And / Or 演算子 : 完全評価( Complete )型 と 短絡評価( Short-circuit )型
・ オーソドックス な 「表引き」 手法との比較
・ 祝日判定の拡張 ( 土日も含める 等 ) について
・ 拡張マクロ : 銀行休日の判定
・ 5月6日 ( 振替休日 ) の判定方法について
・ 2019年GWの休日(4/30,5/1,5/2) の判定方法について
・ ( 番外 ) 新元号対応 日付変換関数 EraFormat / EraCDate
1 --言語-- -- 移 植 -- -公開日- -頁- VB/VBA AddinBox(角田) 2002/ 3/16 1 Delphi AddinBox(角田) 2002/11/22 〃 JavaScript AddinBox(角田) 2003/ 5/ 9 〃 OOoBasic AddinBox(角田) 2005/ 4/15 〃 VB2005 Fukuchi さん 2006/ 7/ 4 2 VBS 立野 徹 さん 2003/ 3/ 2 〃 PHP 代理店どっとこむ「中野」 さん 2003/ 5/ 6 〃 C こほろぎ AsaPi! さん 2003/ 3/ 2 3 C# 小山 隆史 さん 2005/12/17 〃 Perl 富士ソフトサービスビューロ(株)
BS部 「稲葉」 さん2003/ 6/ 9 〃 AWK 富士ソフトサービスビューロ(株)
BS部 「稲葉」 さん2003/ 6/11 〃 Apollo たけ(tk) さん 2003/ 9/24 4 Ruby たけ(tk) さん 2005/ 4/15 〃 JAVA 阿蛭 栄一 さん 2003/12/21 〃 Transact-SQL シリコンブレス 有方 公一 さん 2006/ 8/ 1 5 PL/SQL 菅 康明 さん 2006/12/ 1 〃 Python 瀬戸口 光宏 さん 2007/ 5/28 〃 ActionScript 3 stocksrc.com 2010/ 3/23 6 Go 言語 杉田 臣輔 さん 2015/ 1/ 6 〃 Scala gakuzzzz さん 2019/ 1/17 〃
開発での利用も可(フリー/シェアでの利用の場合、事後で結構ですので一言
お知らせください)です。ただし、引用に当たっては、マクロの先頭に記述してある
コメント(CopyRight )を必ず一緒に引用する事
を条件とします。
なお、他サイト上で本コードを直接引用する事は、ご遠慮願います。本ページへの
リンクによる紹介で対応して下さい。
[ktHolidayName]という関数名そのものは、各自の環境における命名規則に沿って
変更しても構いません。
VBA(VB含む)で利用する場合はマクロのコード構成を一切変更しないでください。
VBAというレスポンス的に不利な言語でも出来る限りレスポンスを良くする事を前提に
設計してある為、コード内容を変更するとレスポンスが低下する可能性があります。
VBA以外の言語に移植する場合は、その言語の特性に合わせたベストなコード構成に
変更しても構いません。
また、出来上がったものをご連絡頂ければ、このページにて紹介させて貰います。
尚、移植に際しては、And/Orによる条件演算、および[春分の日/秋分の日]算出式の
INT演算について各言語特性に留意して下さい。また、表引き手法を採らない理由も
御一読ください。
[ Note ]
Access などで、[Null値]を受け取る/返すといった必要がある場合には、下記のように
『ktHolidayName 』の外側に、もうひとつ関数を被せるようにする事で『ktHolidayName 』
自体は変更せずに利用する事ができます(この場合には、ktHolidayName は'Private'に
して下さい)。尚、下記はVBA(VB)コードによる例です。
Public Function 祝日名(ByVal 日付 As Variant) As Variant
If IsDate(日付) Then
祝日名 = ktHolidayName(CDate(日付))
Else
祝日名 = Null
End If
End Function
その他に「銀行休日」で「土日休み」部分も一緒にフォローしたいといった場合でも
同様の方法で対応できます。
Public Function 祝日_土日(ByVal 日付 As Date) As String
祝日_土日 = ktHolidayName(日付)
If (祝日_土日 = "") Then
Select Case Weekday(日付)
Case vbSunday: 祝日_土日 = "日"
Case vbSaturday: 祝日_土日 = "土"
Case Else
End Select
End If
End Function
このようにする事で[ktHolidayName]のロジック自体を変更せずに、様々な条件を付け加える
事が可能です。引用する際には[ktHolidayName]そのものには手を加えずに、コメントを含めて
丸々コピーするようにしてください。
ktHolidayName/prv祝日 の内部に処理を追加してしまうと、将来再び祝日法が変更された
場合に、新しいktHolidayName/prv祝日 の上書き修正により、追加した処理が消えてしま
います。そうならない為にも、ktHolidayName/prv祝日には手を加えずに、その外側にプロシ
ジャーを用意して、そこで機能追加を施すようにして下さい。
[ この場所へのリンク ]
【 Transact-SQL 用祝日判定コード 】 [ 検証用データ ( 祝日一覧 ) は JavaScript 版による ツール で取得できます ] [ 不具合報告 メール送信 ]
2006/8/1 追記 ( [昭和の日] 改正 対応済 )
2014/5/29 [山の日]改正の修正
2018/2/15 [天皇誕生日の変更]改正の修正
2018/6/21 一部修正( 下記参照 )
2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
2018/12/8 [即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
2020/11/28 [五輪特措法による祝日移動(2021年)] 改正の修正
VBAコードのロジックを、そのまま[Transact-SQL ]用に書き直したものです。
シリコンブレス「有方 公一」さんによる編集です。この祝日機能を搭載したHP向け
カレンダーツール の提供もされてます。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
『祝日について』
「昭和の日」に伴う「振替休日(5月6日)」改正への修正方針もお読みください。
「即位の日(2019/5/1)」に伴う「祝日に挟まれた平日(4/30 & 5/2)の休日化」への修正方針もお読みください。
--- 修正内容の説明 --------------------------------------
2018/6/21 : 修正前ソースコード ( Internet Archive )
5月6日が [水曜, 憲法記念日(5/3) の振替休日] の判定が抜けていました。
[2009/5/6(水), 2015/5/6(水), 2020/5/6(水), … ] が「平日」と判定されていました。
if(@intDay = 6)
begin
if(@intYear >= 2007)
begin
if(DATEPART(weekday,@prmTargetDate) = 2 or DATEPART(weekday,@prmTargetDate) = 3)
begin
--火曜日または水曜日[5/3,5/4が日曜]ケースのみ
set @HolidayString = '振替休日'
end
end
火曜(3) / 水曜(4) ですので以下のように修正します。
if(DATEPART(weekday,@prmTargetDate) = 3 or DATEPART(weekday,@prmTargetDate) = 4) -- Tuesday(3), Wednesday(4)
-----------------------------------------------------------
----------- Transact-SQL における 曜日値について -----------
曜日の値は [ 日(1), 月(2), 火(3), 水(4), 木(5), 金(6), 土(7) ] です。
システム定数は用意されていません。
(補) Transact-SQL では、環境設定によって、曜日値の並びが変わります ( [ 月(1), 火(2), … 日(7) ] 等 )。
このプログラムは曜日値 ( DATEPART(weekday, 日付) ) が [ 日(1), 月(2) ... 土(7) ] である前提で作成しています
したがって、SET DATEFIRST は省略 (or 7(標準/USA) を指定) してください
usp_GetHolidayStringは、他のストアドから使用できるように、返値用変数を引数にとります。
このため、単独では使用できません。
----------------------------------------------------------------------------------------
CREATE Procedure usp_GetHolidayName
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
--_/
--_/ --- Transact-SQL 移植版 ( Update: 2020/11/28 ) ---
--_/
--_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
--_/ ( AddinBox http://addinbox.sakura.ne.jp/index.htm )
--_/ ( 旧サイト http://www.h3.dion.ne.jp/~sakatsu/index.htm )
--_/
--_/ この祝日マクロは『kt関数アドイン』で使用しているVBAマクロ
--_/ を[Transact-SQL]に移植したものです。
--_/ このロジックは、レスポンスを第一義として、可能な限り少ない
--_/ 【条件判定の実行】で結果を出せるように設計してあります。
--_/
--_/ この関数では以下の祝日変更までサポートしています。
--_/ (a) 2019年施行の「天皇誕生日の変更」 12/23⇒2/23 (補:2019年には[天皇誕生日]はありません)
--_/ (b) 2019年の徳仁親王の即位日(5/1) および
--_/ 祝日に挟まれて「国民の休日」となる 4/30(平成天皇の退位日) & 5/2 の2休日
--_/ (c) 2019年の「即位の礼 正殿の儀 (10/22) 」
--_/ (d) 2020年施行の「体育の日の改名」⇒スポーツの日
--_/ (e) 五輪特措法による2020年の「祝日移動」
--_/ 海の日:7/20(3rd Mon)⇒7/23, スポーツの日:10/12(2nd Mon)⇒7/24, 山の日:8/11⇒8/10
--_/ (f) 五輪特措法による2021年の「祝日移動」
--_/ 海の日:7/19(3rd Mon)⇒7/22, スポーツの日:10/11(2nd Mon)⇒7/23, 山の日:8/11⇒8/8
--_/
--_/ (*1)このマクロを引用するに当たっては、必ずこのコメントも
--_/ 一緒に引用する事とします。
--_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
--_/ 【 http://addinbox.sakura.ne.jp/holiday_logic.htm 】
--_/ へのリンクによる紹介で対応して下さい。
--_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に
--_/ おける命名規則に沿って変更しても構いません。
--_/
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
--
-- 2014/5/29 [山の日]改正の修正
-- 2018/2/15 [天皇誕生日の変更]改正の修正
-- 2018/6/21 5月6日(水曜, 憲法記念日(5/3)の振替休日)の判定が抜けていたのを修正
-- 2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
-- 2018/12/8 [即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
-- 2020/11/28 [五輪特措法による祝日移動(2021年)] 改正の修正
--
--
--【機能】休日名を取得する
--【引数】@prmTargetDate 対象日付
--【戻値】休日名
--【備考】usp_GetHolidayStringで祝日を取得し、
-- このストアドで振替休日判定をおこなう
--
-- ※ 注意事項 ※
-- このプログラムは曜日値( DATEPART(weekday,日付) )が「日(1), 月(2) ... 土(7)」である前提で作成しています
-- したがって、SET DATEFIRST は省略 (or 7(標準/USA) を指定) してください
-- それ以外の設定では正しく動作しません(プログラムの修正が必要になります)
@prmTargetDate datetime
,@HolidayName varchar(20) OUTPUT
As
set nocount on
declare @FrSiko datetime --振替休日施行日
set @FrSiko = CONVERT(datetime,'1973/04/12')
set @HolidayName = ''
----- 祝日名を取得 -----
exec usp_GetHolidayString @prmTargetDate,@HolidayName OUTPUT
-- ----- 振替休日の判定 (振替休日施行日:1973/4/12) -----
-- [ 対象日≠祝日/休日 & 対象日=月曜日 ]のみ、前日(=日曜日)を祝日判定する。
-- 前日(=日曜日)が祝日の場合は”振替休日”となる。
-- 尚、5月6日の扱いを
-- 「火曜 or 水曜(みどりの日(5/4) or 憲法記念日(5/3)の振替休日)」⇒5月ブロック内で判定済
-- 「月曜(こどもの日(5/5)の振替休日」⇒ここの判定処理で判定
-- とする事により、ここでの判定対象は『対象日が月曜日』のみ となります。
if(@HolidayName = '')
begin
if(DATEPART(weekday,@prmTargetDate) = 2) -- Monday(2)
begin
if(@prmTargetDate >= @FrSiko) -- (1973/04/12)
begin
--前日の祝日名を取得
set @prmTargetDate=DATEADD(day,-1,@prmTargetDate)
exec usp_GetHolidayString @prmTargetDate,@HolidayName OUTPUT
if(@HolidayName <> '')
set @HolidayName = '振替休日'
end
end
end
CREATE Procedure usp_GetHolidayString
--【機能】祝日名の取得
--【引数】@prmTargetDate 対象日付
--【戻値】祝日名
--【備考】usp_GetHolidayNameから使用する
@prmTargetDate datetime
,@HolidayString varchar(20) OUTPUT
As
set nocount on
declare @HoSiko datetime --祝日法施行
declare @Showa_Taiso datetime --昭和天皇大喪の礼
declare @Akihito_Kekkon datetime --明仁親王の結婚の儀
declare @Naruhito_Kekkon datetime --徳仁親王の結婚の儀
declare @SokuireiSeiden datetime --即位礼正殿の儀(平成天皇)
declare @Taii_Heisei datetime --平成天皇の退位日(祝日ではなく「国民の休日」です)
declare @Sokui_Naruhito datetime --即位日(徳仁親王)
declare @Holiday_2019May2 datetime --祝日ではなく「国民の休日」です
declare @SokuireiSeiden_Naruhito datetime --即位礼正殿の儀(徳仁親王)
declare @Syunbun int --春分の日
declare @Syuubun int --秋分の日
declare @intYear int
declare @intMonth int
declare @intDay int
declare @Youbi varchar(10)
--時刻データ(小数部)は取り除いてあるので、下記の@prmTargetDateとの比較はOK
set @HoSiko = CONVERT(datetime,'1948/07/20') --祝日法施行
set @Showa_Taiso = CONVERT(datetime,'1989/02/24') --昭和天皇の大喪の礼
set @Akihito_Kekkon = CONVERT(datetime,'1959/04/10') --明仁親王の結婚の儀
set @Naruhito_Kekkon = CONVERT(datetime,'1993/06/09') --徳仁親王の結婚の儀
set @SokuireiSeiden = CONVERT(datetime,'1990/11/12') --即位礼正殿の儀(平成天皇)
set @Taii_Heisei = CONVERT(datetime,'2019/04/30') --平成天皇の退位日(祝日ではなく「国民の休日」です)
set @Sokui_Naruhito = CONVERT(datetime,'2019/05/01') --即位日(徳仁親王)
set @Holiday_2019May2 = CONVERT(datetime,'2019/05/02') --祝日ではなく「国民の休日」です
set @SokuireiSeiden_Naruhito = CONVERT(datetime,'2019/10/22') --即位礼正殿の儀(徳仁親王)
set @intYear = Year(@prmTargetDate)
set @intMonth = Month(@prmTargetDate) -- 月(1〜12)
set @intDay = Day(@prmTargetDate)
set @HolidayString = ''
-- 祝日法施行以前 --
if(@prmTargetDate < @HoSiko)
return
else
---- 祝日の判定 ----
-- 1月 --
if(@intMonth = 1)
begin
if(@intDay = 1)
set @HolidayString = '元日'
else
begin
if(@intYear >= 2000)
begin
set @Youbi = CONVERT(varchar,((@intDay - 1) / 7) + 1)
+ CONVERT(varchar,DATEPART(weekday,@prmTargetDate))
if(@Youbi = '22') -- 2nd Monday(2)
set @HolidayString = '成人の日'
end
else
begin
if(@intDay = 15)
set @HolidayString = '成人の日'
end
end
end
else
-- 2月 --
if(@intMonth = 2)
begin
if(@intDay = 11)
begin
if(@intYear >= 1967)
set @HolidayString = '建国記念の日'
end
else
begin
if(@intDay = 23)
begin
if(@intYear >= 2020)
set @HolidayString = '天皇誕生日'
end
else
begin
if(@prmTargetDate = @Showa_Taiso) -- (1989/2/24)
set @HolidayString = '昭和天皇の大喪の礼'
end
end
end
else
-- 3月 --
if(@intMonth = 3)
begin
-- 春分/秋分日の略算式は
-- 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』
-- で紹介されている式です。
if(@intYear <= 1947)
set @Syunbun = 99 --祝日法施行前
else
begin
if(@intYear <= 1979)
set @Syunbun = CONVERT(int,20.8357 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
begin
if(@intYear <= 2099)
set @Syunbun = CONVERT(int,20.8431 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
begin
if(@intYear <= 2150)
set @Syunbun = CONVERT(int,20.851 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
set @Syunbun = 99 --2151年以降は略算式が無いので不明
end
end
end
if(@intDay = @Syunbun) -- 1948〜2150以外は[99]が返るので、必ず≠になる
set @HolidayString = '春分の日'
end
else
-- 4月 --
if(@intMonth = 4)
begin
if(@intDay = 29)
begin
if(@intYear >= 2007)
set @HolidayString = '昭和の日'
else
begin
if(@intYear >= 1989)
set @HolidayString = 'みどりの日'
else
set @HolidayString = '天皇誕生日' --昭和天皇
end
end
else
begin
if(@prmTargetDate = @Taii_Heisei) -- (2019/4/30)
set @HolidayString = '国民の休日' --平成天皇の退位日(祝日ではなく「国民の休日」です)
else
begin
if(@prmTargetDate = @Akihito_Kekkon) -- (1959/4/10)
set @HolidayString = '皇太子明仁親王の結婚の儀'
end
end
end
else
-- 5月 --
if(@intMonth = 5)
begin
if(@intDay = 3)
set @HolidayString = '憲法記念日'
else
begin
if(@intDay = 4)
begin
if(@intYear >= 2007)
set @HolidayString = 'みどりの日'
else
begin
if(@intYear >= 1986)
begin
if(DATEPART(weekday,@prmTargetDate) > 2) -- Monday(2) , 火曜 以降(火〜土)
--5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』
set @HolidayString = '国民の休日'
  end
end
end
else
begin
if(@intDay = 5)
set @HolidayString = 'こどもの日'
else
begin
if(@intDay = 6)
begin
if(@intYear >= 2007)
begin
if(DATEPART(weekday,@prmTargetDate) = 3
or DATEPART(weekday,@prmTargetDate) = 4) -- Tuesday(3), Wednesday(4)
begin
-- 火曜日または水曜日[5/3,5/4が日曜]ケースのみ
set @HolidayString = '振替休日'
end
end
end
else
begin
if(@prmTargetDate = @Sokui_Naruhito) -- (2019/5/1)
set @HolidayString = '即位の日' --徳仁親王
else
begin
if(@prmTargetDate = @Holiday_2019May2) -- (2019/5/2)
set @HolidayString = '国民の休日' --祝日ではなく「国民の休日」です
end
end
end
end
end
end
else
-- 6月 --
if(@intMonth = 6)
begin
if(@prmTargetDate = @Naruhito_Kekkon) -- (1993/6/9)
set @HolidayString = '皇太子徳仁親王の結婚の儀'
end
else
-- 7月 --
if(@intMonth = 7)
begin
set @Youbi = CONVERT(varchar,((@intDay - 1) / 7) + 1)
+ CONVERT(varchar,DATEPART(weekday,@prmTargetDate))
if(@intYear >= 2022)
begin
if(@Youbi = '32') -- 3rd Monday(2)
set @HolidayString = '海の日'
end
else
begin
if(@intYear = 2021)
begin
-- 2021年はオリンピック特措法により
--「海の日」が 7/22 , 「スポーツの日」が 7/23 に移動
if(@intDay = 22)
set @HolidayString = '海の日'
else
begin
if(@intDay = 23)
set @HolidayString = 'スポーツの日'
end
end
else
begin
if(@intYear = 2020)
begin
-- 2020年はオリンピック特措法により
--「海の日」が 7/23 , 「スポーツの日」が 7/24 に移動
if(@intDay = 23)
set @HolidayString = '海の日'
else
begin
if(@intDay = 24)
set @HolidayString = 'スポーツの日'
end
end
else
begin
if(@intYear >= 2003)
begin
if(@Youbi = '32') -- 3rd Monday(2)
set @HolidayString = '海の日'
end
else
begin
if(@intYear >= 1996)
if(@intDay = 20)
set @HolidayString = '海の日'
end
end
end
end
end
else
-- 8月 --
if(@intMonth = 8)
begin
if(@intYear >= 2022)
begin
if(@intDay = 11)
set @HolidayString = '山の日'
end
else
begin
if(@intYear = 2021)
begin
-- 2021年はオリンピック特措法により「山の日」が 8/8 に移動
if(@intDay = 8)
set @HolidayString = '山の日'
end
else
begin
if(@intYear = 2020)
begin
-- 2020年はオリンピック特措法により「山の日」が 8/10 に移動
if(@intDay = 10)
set @HolidayString = '山の日'
end
else
begin
if(@intYear >= 2016)
begin
if(@intDay = 11)
set @HolidayString = '山の日'
end
end
end
end
end
else
-- 9月 --
if(@intMonth = 9)
begin
--第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない
-- 春分/秋分日の略算式は
-- 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』
-- で紹介されている式です。
if(@intYear <= 1947)
set @Syuubun = 99 --祝日法施行前
else
begin
if(@intYear <= 1979)
set @Syuubun = CONVERT(int,23.2588 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
begin
if(@intYear <= 2099)
set @Syuubun = CONVERT(int,23.2488 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
begin
if(@intYear <= 2150)
set @Syuubun = CONVERT(int,24.2488 + (0.242194 * (@intYear - 1980)) - CONVERT(int,(@intYear - 1980) / 4))
else
set @Syuubun = 99 --2151年以降は略算式が無いので不明
end
end
end
if(@intDay = @Syuubun) -- 1948〜2150以外は[99]が返るので、必ず≠になる
set @HolidayString = '秋分の日'
else
begin
if(@intYear >= 2003)
begin
set @Youbi = CONVERT(varchar,((@intDay - 1) / 7) + 1)
+ CONVERT(varchar,DATEPART(weekday,@prmTargetDate))
if(@Youbi = '32') -- 3rd Monday(2)
set @HolidayString = '敬老の日'
else
begin
if(DATEPART(weekday,@prmTargetDate) = 3) -- Tuesday(3)
begin
if(@intDay = (@Syuubun - 1))
set @HolidayString = '国民の休日' -- 火曜日&[秋分日の前日]
end
end
end
else
begin
if(@intYear >= 1966)
begin
if(@intDay = 15)
set @HolidayString = '敬老の日'
end
end
end
end
else
-- 10月 --
if(@intMonth = 10)
begin
set @Youbi = CONVERT(varchar,((@intDay - 1) / 7) + 1)
+ CONVERT(varchar,DATEPART(weekday,@prmTargetDate))
if(@intYear >= 2022)
begin
if(@Youbi = '22') -- 2nd Monday(2)
set @HolidayString = 'スポーツの日' -- 2020年より改名
end
else
begin
if((@intYear = 2020) OR (@intYear = 2021))
begin
-- 2021年はオリンピック特措法により「スポーツの日」が 7/23 に移動
-- 2020年はオリンピック特措法により「スポーツの日」が 7/24 に移動
end
else
begin
if(@intYear >= 2000)
begin
if(@Youbi = '22') -- 2nd Monday(2)
set @HolidayString = '体育の日'
else
begin
if(@prmTargetDate = @SokuireiSeiden_Naruhito) -- (2019/10/22)
set @HolidayString = '即位礼正殿の儀' -- 徳仁親王
end
end
else
begin
if(@intYear >= 1966)
begin
if(@intDay = 10)
set @HolidayString = '体育の日'
end
end
end
end
end
else
-- 11月 --
if(@intMonth = 11)
begin
if(@intDay = 3)
set @HolidayString = '文化の日'
else
begin
if(@intDay = 23)
set @HolidayString = '勤労感謝の日'
else
begin
if(@prmTargetDate = @SokuireiSeiden) -- (1990/11/12)
set @HolidayString = '即位礼正殿の儀' -- 平成天皇
end
end
end
else
-- 12月 --
if(@intMonth = 12)
begin
if(@intDay = 23)
begin
if((@intYear >= 1989) AND (@intYear <= 2018))
set @HolidayString = '天皇誕生日' --平成天皇
end
end
return
[ この場所へのリンク ]
【 Oracle PL/SQL 用祝日判定コード 】 [ 検証用データ ( 祝日一覧 ) は JavaScript 版による ツール で取得できます ] [ 不具合報告 メール送信 ]
2006/12/1 追記 ( [昭和の日]改正 対応済み )
2014/5/29 [山の日]改正の修正
2018/2/15 [天皇誕生日の変更]改正の修正
2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
2018/12/8 [即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
2018/12/8 一部修正( 下記参照 )
2020/11/28 [五輪特措法による祝日移動(2021年)] 改正の修正
VBAコードのロジックを、そのまま[PL/SQL(Oracle9i) ]用に書き直したものです。
「菅 康明」さんによる編集です。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
『祝日について』
「昭和の日」に伴う「振替休日(5月6日)」改正への修正方針もお読みください。
「即位の日(2019/5/1)」に伴う「祝日に挟まれた平日(4/30 & 5/2)の休日化」への修正方針もお読みください。
--- 修正内容の説明 --------------------------------------
2018/12/8
IF ELSE 等の命令文が、引用元の VBA コード由来で小文字混じりの記述になっていましたので、大文字に改めました。
If 〜 Then / Else 〜 / End If 等 ⇒ IF 〜 THEN / ELSE 〜 / END IF 等
-----------------------------------------------------------
----------- PL/SQL における 曜日値について -----------
曜日の値は [ 日(1), 月(2), 火(3), 水(4), 木(5), 金(6), 土(7) ] です。
システム定数は用意されていません。
(補) PL/SQL では、環境設定によって、曜日値の並びが変わります ( [ 月(1), 火(2), … 日(7) ] 等 )。
このプログラムは曜日値 ( TO_CHAR(日付,'D') ) が [ 日(1), 月(2) ... 土(7) ] である前提で作成しています
----------------------------------------------------------------------------------------
CREATE OR REPLACE PACKAGE ktHolidayName IS
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
--_/
--_/ --- PL/SQL 移植版 ( Update: 2020/11/28 ) ---
--_/
--_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
--_/ ( AddinBox http://addinbox.sakura.ne.jp/index.htm )
--_/ ( 旧サイト http://www.h3.dion.ne.jp/~sakatsu/index.htm )
--_/
--_/ この祝日マクロは『kt関数アドイン』で使用しているものです。
--_/ このロジックは、レスポンスを第一義として、可能な限り少ない
--_/ 【条件判定の実行】で結果を出せるように設計してあります。
--_/
--_/ この関数では以下の祝日変更までサポートしています。
--_/ (a) 2019年施行の「天皇誕生日の変更」 12/23⇒2/23 (補:2019年には[天皇誕生日]はありません)
--_/ (b) 2019年の徳仁親王の即位日(5/1) および
--_/ 祝日に挟まれて「国民の休日」となる 4/30(平成天皇の退位日) & 5/2 の2休日
--_/ (c) 2019年の「即位の礼 正殿の儀 (10/22) 」
--_/ (d) 2020年施行の「体育の日の改名」⇒スポーツの日
--_/ (e) 五輪特措法による2020年の「祝日移動」
--_/ 海の日:7/20(3rd Mon)⇒7/23, スポーツの日:10/12(2nd Mon)⇒7/24, 山の日:8/11⇒8/10
--_/ (f) 五輪特措法による2021年の「祝日移動」
--_/ 海の日:7/19(3rd Mon)⇒7/22, スポーツの日:10/11(2nd Mon)⇒7/23, 山の日:8/11⇒8/8
--_/
--_/ (*1)このマクロを引用するに当たっては、必ずこのコメントも
--_/ 一緒に引用する事とします。
--_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
--_/ 【 http://addinbox.sakura.ne.jp/holiday_logic.htm 】
--_/ へのリンクによる紹介で対応して下さい。
--_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に
--_/ おける命名規則に沿って変更しても構いません。
--_/
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
--
-- 2014/5/29 [山の日]改正の修正
-- 2018/2/15 [天皇誕生日の変更]改正の修正
-- 2018/6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
-- 2018/12/8 [即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
-- 2018/12/8 IF ELSE 等の命令文が「引用元のVBAコード由来で小文字混じりの記述」になっていましたので、大文字に改めました。
-- 2020/11/28 [五輪特措法による祝日移動(2021年)] 改正の修正
--
-- =============================================================================
-- ==【PL/SQL用祝日判定コード 】 2006/11/29(Wed) 追記
-- ==VBAコードのロジックを、そのまま[PL/SQL]用に書き直したものです。
-- ==
-- ==■環境依存
-- ==・TO_CHAR(日時)関数の戻り値について
-- ==
-- ==曜日取得の際に使用している TO_CHAR(日時)の'D'の戻り値については [ 日(1),月(2) ... 土(7) ]
-- ==として扱っていますが、この値は環境に依存します。
-- ==もし、[ 月(1) ... 土(6),日(7)]となる場合は以下の修正が必要となります。
-- == (1) パッケージ定数 vbMonday 〜 vbWednesday の値変更
-- == (2) 成人の日/海の日/敬老の日/体育の日の判定における
-- == If (str第N曜日 = '22') Then -- 2nd Monday(2) および
-- == If (str第N曜日 = '32') Then -- 3rd Monday(2)
-- == で各々[21][31]に修正する必要があります。
-- == (3) 5月4日の判定における
-- == If (TO_CHAR(日付,'D') > vbMonday) Then -- 火曜 以降(火〜土)
-- == を修正する必要があります。
-- ==
-- ==※Oracle9i SQLリファレンス リリース2(9.2)2003 年2月 部品番号: J06261-02
-- == より抜粋
-- ==日時書式要素D は、曜日の数(1 〜 7)を戻します。この数が1 である曜日は、
-- ==初期化パラメータNLS_TERRITORY によって暗黙的に指定されます。
-- ==
-- ==・CASE文について
-- ==CASE文 Oracle9i にて採用された構文です。
-- ==Oracle9i 以前のDBMSを使用している場合は、IF-ELSIFに置き換えてください。
-- ==
-- ==・データ型
-- ==VBA版はIntegerを使っているが、PL/SQL版はNUMBERを使用。
-- ==
-- =============================================================================
FUNCTION ktHolidayName( 日付 IN DATE ) RETURN VARCHAR2;
END ktHolidayName;
/
-- ****************************************************************************
-- *** Package Body Start
-- ****************************************************************************
CREATE OR REPLACE PACKAGE BODY ktHolidayName IS
--グローバル変数定義(vb定数が無いもの) [ 日(1),月(2) ... 土(7) ]
vbMonday CONSTANT NUMBER := 2;
vbTuesday CONSTANT NUMBER := 3;
vbWednesday CONSTANT NUMBER := 4;
-- プログラム内部使用関数プロトタイプ宣言
FUNCTION prv祝日 ( 日付 IN DATE ) RETURN VARCHAR2;
FUNCTION prv春分日 ( 年 IN NUMBER ) RETURN NUMBER;
FUNCTION prv秋分日 ( 年 IN NUMBER ) RETURN NUMBER;
-- ****************************************************************************
-- *** Main Function
-- ****************************************************************************
FUNCTION ktHolidayName( 日付 IN DATE )
RETURN VARCHAR2 IS
--変数定義
dtm日付 DATE;
str祝日名 VARCHAR2(30);
--定数定義
cst振替休日施行日 CONSTANT DATE := TO_DATE('19730412','YYYYMMDD');
BEGIN
--時刻/時刻誤差の削除(SYSDATE関数などへの対応)
dtm日付 := TO_DATE( TO_CHAR(日付,'YYYY') || TO_CHAR(日付,'MM') || TO_CHAR(日付,'DD') , 'YYYYMMDD');
str祝日名 := prv祝日(dtm日付);
-- ----- 振替休日の判定 (振替休日施行日:1973/4/12) -----
-- [ 対象日≠祝日/休日 & 対象日=月曜日 ]のみ、前日(=日曜日)を祝日判定する。
-- 前日(=日曜日)が祝日の場合は”振替休日”となる。
-- 尚、5月6日の扱いを
-- 「火曜 or 水曜(みどりの日(5/4) or 憲法記念日(5/3)の振替休日)」⇒5月ブロック内で判定済
-- 「月曜(こどもの日(5/5)の振替休日」⇒ここの判定処理で判定
-- とする事により、ここでの判定対象は『対象日が月曜日』のみ となります。
IF (str祝日名 IS NULL) THEN
IF (TO_CHAR(dtm日付,'D') = vbMonday) THEN
IF (dtm日付 >= cst振替休日施行日) THEN -- ( 1973/4/12 )
str祝日名 := prv祝日(dtm日付 - 1);
IF (str祝日名 IS NOT NULL) THEN
RETURN '振替休日';
ELSE
RETURN NULL;
END IF;
ELSE
RETURN NULL;
END IF;
ELSE
RETURN NULL;
END IF;
ELSE
RETURN str祝日名;
END IF;
END ktHolidayName;
-- ****************************************************************************
-- *** Sub Function prv祝日
-- ****************************************************************************
FUNCTION prv祝日(日付 IN Date)
RETURN VARCHAR2 IS
--変数定義
int年 NUMBER;
int月 NUMBER;
int日 NUMBER;
int秋分日 NUMBER;
str第N曜日 VARCHAR2(2);
--定数定義
-- 時刻データ(小数部)は取り除いてあるので、下記の日付との比較はOK
cst祝日法施行 CONSTANT DATE := TO_DATE('19480720','YYYYMMDD');
cst昭和天皇の大喪の礼 CONSTANT DATE := TO_DATE('19890224','YYYYMMDD');
cst明仁親王の結婚の儀 CONSTANT DATE := TO_DATE('19590410','YYYYMMDD');
cst徳仁親王の結婚の儀 CONSTANT DATE := TO_DATE('19930609','YYYYMMDD');
cst即位礼正殿の儀 CONSTANT DATE := TO_DATE('19901112','YYYYMMDD'); -- 平成天皇
cst平成天皇の退位 CONSTANT DATE := TO_DATE('20190430','YYYYMMDD'); -- 祝日ではなく「国民の休日」です
cst徳仁親王の即位 CONSTANT DATE := TO_DATE('20190501','YYYYMMDD');
cst2019GW国民の休日 CONSTANT DATE := TO_DATE('20190502','YYYYMMDD'); -- 祝日ではなく「国民の休日」です
cst即位礼正殿の儀_徳仁親王 CONSTANT DATE := TO_DATE('20191022','YYYYMMDD');
BEGIN
int年 := TO_NUMBER(TO_CHAR(日付,'YYYY'));
int月 := TO_NUMBER(TO_CHAR(日付,'MM'));
int日 := TO_NUMBER(TO_CHAR(日付,'DD'));
IF (日付 < cst祝日法施行) THEN -- ( 1948/7/20 )
RETURN NULL; -- 祝日法施行以前
END IF;
CASE int月
-- 1月 --
WHEN 1 THEN
IF (int日 = 1) THEN
RETURN '元日';
ELSE
IF (int年 >= 2000) THEN
str第N曜日 := TO_CHAR(TRUNC((int日 - 1) / 7) + 1,'FM0') || TO_CHAR(日付,'D');
IF (str第N曜日 = '22') THEN -- 2nd Monday(2)
RETURN '成人の日';
END IF;
ELSE
IF (int日 = 15) THEN
RETURN '成人の日';
END IF;
END IF;
END IF;
-- 2月 --
WHEN 2 THEN
IF (int日 = 11) THEN
IF (int年 >= 1967) THEN
RETURN '建国記念の日';
END IF;
ELSIF (int日 = 23) THEN
IF (int年 >= 2020) THEN
RETURN '天皇誕生日';
END IF;
ELSIF (日付 = cst昭和天皇の大喪の礼) THEN -- ( 1989/2/24 )
RETURN '昭和天皇の大喪の礼';
END IF;
-- 3月 --
WHEN 3 THEN
IF (int日 = prv春分日(int年)) THEN -- 1948〜2150以外は[99]が返るので、必ず≠になる
RETURN '春分の日';
END IF;
-- 4月 --
WHEN 4 THEN
IF (int日 = 29) THEN
IF (int年 >= 2007) THEN
RETURN '昭和の日';
ELSIF (int年 >= 1989) THEN
RETURN 'みどりの日';
ELSE
RETURN '天皇誕生日'; -- 昭和天皇
END IF;
ELSIF (日付 = cst平成天皇の退位) THEN -- ( 2019/4/30 )
RETURN '国民の休日';
ELSIF (日付 = cst明仁親王の結婚の儀) THEN -- ( 1959//10 )
RETURN '皇太子明仁親王の結婚の儀';
END IF;
-- 5月 --
WHEN 5 THEN
IF (int日 = 3) THEN
RETURN '憲法記念日';
ELSIF (int日 = 4) THEN
IF (int年 >= 2007) THEN
RETURN 'みどりの日';
ELSIF (int年 >= 1986) THEN
-- 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年)
IF (TO_CHAR(日付,'D') > vbMonday) THEN -- 火曜 以降(火〜土)
RETURN '国民の休日';
END IF;
END IF;
ELSIF (int日 = 5) THEN
RETURN 'こどもの日';
ELSIF (int日 = 6) THEN
IF (int年 >= 2007) THEN
IF ( TO_CHAR(日付,'D') in ( vbTuesday, vbWednesday )) THEN
RETURN '振替休日'; -- 火曜日または水曜日 [5/3,5/4が日曜]ケースのみ、ここで判定
END IF;
END IF;
ELSE
IF (int年 = 2019) THEN
IF (日付 = cst徳仁親王の即位) THEN -- (2019/5/1)
RETURN '即位の日'; -- (徳仁親王)
ELSIF (日付 = cst2019GW国民の休日) THEN -- (2019/5/2)
RETURN '国民の休日'; -- (祝日に挟まれた国民の休日です)
END IF;
END IF;
END IF;
-- 6月 --
WHEN 6 THEN
IF (日付 = cst徳仁親王の結婚の儀) THEN -- ( 1993/6/9 )
RETURN '皇太子徳仁親王の結婚の儀';
END IF;
-- 7月 --
WHEN 7 THEN
str第N曜日 := TO_CHAR(TRUNC((int日 - 1) / 7) + 1,'FM0') || TO_CHAR(日付,'D');
IF (int年 >= 2022) THEN
IF (str第N曜日 = '32') THEN -- 3rd Monday(2)
RETURN '海の日';
END IF;
ELSIF (int年 = 2021) THEN
-- 2021年はオリンピック特措法により
--「海の日」が 7/22 , 「スポーツの日」が 7/23 に移動
IF (int日 = 22) THEN
RETURN '海の日';
ELSIF (int日 = 23) THEN
RETURN 'スポーツの日';
END IF;
ELSIF (int年 = 2020) THEN
-- 2020年はオリンピック特措法により
--「海の日」が 7/23 , 「スポーツの日」が 7/24 に移動
IF (int日 = 23) THEN
RETURN '海の日';
ELSIF (int日 = 24) THEN
RETURN 'スポーツの日';
END IF;
ELSIF (int年 >= 2003) THEN
IF (str第N曜日 = '32') THEN -- 3rd Monday(2)
RETURN '海の日';
END IF;
ELSIF (int年 >= 1996) THEN
IF (int日 = 20) THEN
RETURN '海の日';
END IF;
END IF;
-- 8月 --
WHEN 8 THEN
IF (int年 >= 2022) THEN
IF (int日 = 11) THEN
RETURN '山の日';
END IF;
ELSIF (int年 = 2021) THEN
-- 2021年はオリンピック特措法により「山の日」が 8/8 に移動
IF (int日 = 8) THEN
RETURN '山の日';
END IF;
ELSIF (int年 = 2020) THEN
-- 2020年はオリンピック特措法により「山の日」が 8/10 に移動
IF (int日 = 10) THEN
RETURN '山の日';
END IF;
ELSIF (int年 >= 2016) THEN
IF (int日 = 11) THEN
RETURN '山の日';
END IF;
END IF;
-- 9月 --
WHEN 9 THEN
--第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない
int秋分日 := prv秋分日(int年);
IF (int日 = int秋分日) THEN -- 1948〜2150以外は[99]が返るので、必ず≠になる
RETURN '秋分の日';
ELSE
IF (int年 >= 2003) THEN
str第N曜日 := TO_CHAR(TRUNC((int日 - 1) / 7) + 1,'FM0') || TO_CHAR(日付,'D');
IF (str第N曜日 = '32') THEN -- 3rd Monday(2)
RETURN '敬老の日';
ELSIF (TO_CHAR(日付,'D') = vbTuesday) THEN
IF (int日 = (int秋分日 - 1)) THEN
RETURN '国民の休日'; -- 火曜日&[秋分日の前日]
END IF;
END IF;
ELSIF (int年 >= 1966) THEN
IF (int日 = 15) THEN
RETURN '敬老の日';
END IF;
END IF;
END IF;
-- 10月 --
WHEN 10 THEN
str第N曜日 := TO_CHAR(TRUNC((int日 - 1) / 7) + 1,'FM0') || TO_CHAR(日付,'D');
IF (int年 >= 2022) THEN
IF (str第N曜日 = '22') THEN -- 2nd Monday(2)
RETURN 'スポーツの日'; -- 2020年より改名
END IF;
ELSIF ((int年 = 2020) OR (int年 = 2021)) THEN
-- 2021年はオリンピック特措法により「スポーツの日」が 7/23 に移動
-- 2020年はオリンピック特措法により「スポーツの日」が 7/24 に移動
NULL;
ELSIF (int年 >= 2000) THEN
IF (str第N曜日 = '22') THEN -- 2nd Monday(2)
RETURN '体育の日';
ELSIF (日付 = cst即位礼正殿の儀_徳仁親王) THEN -- (2019/10/22)
RETURN '即位礼正殿の儀'; -- 徳仁親王
END IF;
ELSIF (int年 >= 1966) THEN
IF (int日 = 10) THEN
RETURN '体育の日';
END IF;
END IF;
-- 11月 --
WHEN 11 THEN
IF (int日 = 3) THEN
RETURN '文化の日';
ELSIF (int日 = 23) THEN
RETURN '勤労感謝の日';
ELSIF (日付 = cst即位礼正殿の儀) THEN -- ( 1990/11/12 )
RETURN '即位礼正殿の儀'; -- 平成天皇
END IF;
-- 12月 --
WHEN 12 THEN
IF (int日 = 23) THEN
IF ((int年 >= 1989) AND (int年 <= 2018)) THEN
RETURN '天皇誕生日'; -- 平成天皇
END IF;
END IF;
END CASE;
--この時点で戻り値の無いものは、平日
RETURN NULL;
END prv祝日;
-- ****************************************************************************
-- *** Sub Function prv春分日
-- ****************************************************************************
-- 春分/秋分日の略算式は
-- 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』
-- で紹介されている式です。
FUNCTION prv春分日( 年 IN NUMBER ) RETURN NUMBER
IS
BEGIN
IF (年 <= 1947) THEN
RETURN 99; --祝日法施行前
ELSIF (年 <= 1979) THEN
RETURN TRUNC( 20.8357 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1983) / 4));
ELSIF (年 <= 2099) THEN
RETURN TRUNC( 20.8431 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1980) / 4));
ELSIF (年 <= 2150) THEN
RETURN TRUNC( 21.851 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1980) / 4));
ELSE
RETURN 99; --2151年以降は略算式が無いので不明
END IF;
END prv春分日;
-- ****************************************************************************
-- *** Sub Function prv秋分日
-- ****************************************************************************
FUNCTION prv秋分日( 年 IN NUMBER ) RETURN NUMBER
IS
BEGIN
IF (年 <= 1947) THEN
RETURN 99; --祝日法施行前
ELSIF (年 <= 1979) THEN
RETURN TRUNC(23.2588 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1983) / 4));
ELSIF (年 <= 2099) THEN
RETURN TRUNC(23.2488 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1980) / 4));
ELSIF (年 <= 2150) THEN
RETURN TRUNC(24.2488 + (0.242194 * (年 - 1980)) - TRUNC((年 - 1980) / 4));
ELSE
RETURN 99; --2151年以降は略算式が無いので不明
END IF;
END prv秋分日;
END ktHolidayName;
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
--_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
--_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
/
[ この場所へのリンク ]
【 Python 用祝日判定コード 】 [ 検証用データ ( 祝日一覧 ) は JavaScript 版による ツール で取得できます ] [ 不具合報告 メール送信 ]
2007/ 5/28 追記 ( [昭和の日] 改正 対応済み )
2009/ 1/ 8 不具合修正( 下記参照 )
2010/ 5/ 8 不具合修正( 下記参照 )
2010/ 9/21 一部修正( 下記参照 )
2014/ 5/29 [山の日] 改正の修正
2015/11/30 一部修正( 下記参照 )
2018/ 2/15 [天皇誕生日の変更] 改正の修正
2018/ 6/21 5月4日 及び 振替休日の不具合修正( 下記参照 )
2018/ 6/21 [体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
2018/ 7/20 一部修正( 下記参照 )
2018/12/8 [即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
2020/11/28 [五輪特措法による祝日移動(2021年)] 改正の修正
VBAコードのロジックを、そのまま[ Python ]用に書き直したものです。
「瀬戸口光宏」さんによる編集です。
Python ではプログラムのブロック構造を「インデント」で表現します ( Python とインデント )。
下記コードでは「空白4文字」でインデントしてあります。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
『祝日について』
「昭和の日」に伴う「振替休日(5月6日)」改正への修正方針もお読みください。
「即位の日(2019/5/1)」に伴う「祝日に挟まれた平日(4/30 & 5/2)の休日化」への修正方針もお読みください。
--- 修正内容の説明 --------------------------------------
2009/1/8
秋分日判定( _autumn_equinox ) で4つ目の日付条件が間違っていました。
1979 となっていたのを 2150 に修正しました。
2010/5/8 1:30
春分/秋分判定で、[〜1979年] の場合の式が間違っていました(基本式)。
Python の int 関数は C/FortranのInt , VBAのFix と同じで
小数部の単純な切り落としです( int(8.4)→8 , int(-8.4)→ -8 )。
int((y - 1980) / 4) → int((y - 1983) / 4)
2010/5/8 14:00 再修正
Python 2.x と 3.x で整数同士の除算 ( / ) の結果が異なる点が問題でした。
Python2.x ( 整数同士の除算結果は切捨除算 ( その値を超えない最大の整数 ) )
30 / 4 = 7 , int(30 / 4) = 7 , math.floor(30 / 4) = 7
-30 / 4 = -8 , int(-30 / 4) = -8 , math.floor(-30 / 4) = -8
Python3.x ( 整数同士の除算結果は実数 )
30 / 4 = 7.5 , int(30 / 4) = 7 , math.floor(30 / 4) = 7
-30 / 4 = -7.5 , int(-30 / 4) = -7 (NG) , math.floor(-30 / 4) = -8
負数の場合、Python2.x では [ int((y - 1980) / 4) ] でも大丈夫でしたが、Python3.x では [ int((y - 1983) / 4) ] に
する必要があります。共通して同じ結果が得られる math.floor に変更します ( Python2.2 から切捨除算演算子 ( // ) が
サポートされているが、Python2.0/2.1 でエラーになるので math.floor で統一します)。
int((y - 1980) / 4) → math.floor((y - 1980) / 4)
2010/9/21
(1) holiday_name() の引数で、[年,月,日] による指定方法の他に、datetime.date オブジェクトによる指定方法を
加えました(月ごとの判定処理部分にあった year,month,day は date引数の要素として date.xxx の記述に
変わっています)。
(2) 文字列の扱いに関する Python 2.x/3.x 間の変更に対応しました。
Python 2.x 系以前の場合には Unicode 文字列で、Python 3.x 系以降の場合には文字列で祝日名を
返します(祝日名(文字列リテラル)の記述が u'XXX' から 'XXX' に変わっています。なお、Python2.x 系
以前の場合に unicode変換を行なう処理を追加しています)。
2015/11/30
[ import math ] の記述をコードの先頭に追記。
2018/6/21 : 修正前ソースコード ( Internet Archive )
5月4日 ( 国民の休日:1986〜2006年 ) の判定処理に誤りがありました。
elif date.day == 4:
if date.year >= 2007:
name = 'みどりの日'
elif date.year >= 1986 and date.weekday() != MONDAY:
name = '国民の休日'
この [ date.weekday() != MONDAY ] が間違っていました。 ここでの判定式の本来の意味は、
[ 曜日値が 『 日, 月, 火 〜 土 』 の並びで、曜日値 > 月曜日 ]
です。つまり、火曜〜土曜の範囲が対象です。
Python では曜日値が 『 月(0), 火(1) 〜 土(5), 日(6) 』 の並びであり、しかも、上記では月曜日しか除外していません。
その結果 1986/5/4(日), 1997/5/4(日), 2003/5/4(日) が「国民の休日」と判定されていました。この日付での正解は
『 只の日曜日 ( ≠ 祝日/休日 ) 』 です。 以下のように修正します。
誤) MONDAY, TUESDAY, WEDNESDAY = 0, 1, 2
elif date.year >= 1986 and date.weekday() != MONDAY:
正) MONDAY, TUESDAY, WEDNESDAY, SUNDAY = 0, 1, 2, 6
elif date.year >= 1986 and date.weekday() not in (MONDAY, SUNDAY):
振替休日の判定処理に誤りがありました(振替休日の施行日判定が抜けている)。
if not name and date.weekday() == MONDAY:
prev = date + datetime.timedelta(days = -1)
if holiday_name(prev.year, prev.month, prev.day):
name = '振替休日'
下記に修正します。
if (not name) and (date.weekday() == MONDAY) and (date >= datetime.date(1973, 4, 12)):
2018/7/20
[ import sys ] の記述が抜けていましたので追記しました。
---------------------------------------------------------------------------------
----------- Python における 曜日値について -----------
曜日の値は [ 月(0), 火(1), 水(2), 木(3), 金(4), 土(5), 日(6) ] です。
システム定数は用意されていません。
----------------------------------------------------------------------------------------
※※ Tab インデントの ファイル ( Python_Holiday.py ) を用意してありますのでダウンロードして使って下さい※※
※※ TeraPad を使って UTF-8N (UTF-8 BOM無) 指定で作成してあります。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
// ※※ このコードは「空白4文字」でインデントしてあります ※※
//
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/
//_/ --- Python 移植版 ( Update: 2020/11/28 ) ---
//_/
//_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
//_/ ( AddinBox http://addinbox.sakura.ne.jp/index.htm )
//_/ ( 旧サイト http://www.h3.dion.ne.jp/~sakatsu/index.htm )
//_/
//_/ この祝日判定コードは『Excel:kt関数アドイン』で使用しているものです。
//_/ このロジックは、レスポンスを第一義として、可能な限り少ない
//_/ 【条件判定の実行】で結果を出せるように設計してあります。
//_/
//_/ この関数では以下の祝日変更までサポートしています。
//_/ (a) 2019年施行の「天皇誕生日の変更」 12/23⇒2/23 (補:2019年には[天皇誕生日]はありません)
//_/ (b) 2019年の徳仁親王の即位日(5/1) および
//_/ 祝日に挟まれて「国民の休日」となる 4/30(平成天皇の退位日) & 5/2 の2休日
//_/ (c) 2019年の「即位の礼 正殿の儀 (10/22) 」
//_/ (d) 2020年施行の「体育の日の改名」⇒スポーツの日
//_/ (e) 五輪特措法による2020年の「祝日移動」
//_/ 海の日:7/20(3rd Mon)⇒7/23, スポーツの日:10/12(2nd Mon)⇒7/24, 山の日:8/11⇒8/10
//_/ (f) 五輪特措法による2021年の「祝日移動」
//_/ 海の日:7/19(3rd Mon)⇒7/22, スポーツの日:10/11(2nd Mon)⇒7/23, 山の日:8/11⇒8/8
//_/
//_/ (*1)このコードを引用するに当たっては、必ずこのコメントも
//_/ 一緒に引用する事とします。
//_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
//_/ 【 http://addinbox.sakura.ne.jp/holiday_logic.htm 】
//_/ へのリンクによる紹介で対応して下さい。
//_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に
//_/ おける命名規則に沿って変更しても構いません。
//_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
追記 SETOGUCHI Mitsuhiro http://straitmouth.jp/
* 2007/May/26
このスクリプトは JavaScript 用判定コード
http://addinbox.sakura.ne.jp/holiday_logic.htm#JS
を元に、Python 向けに移植したものです。
holiday_name() は、年、月、日の3つの整数の引数を取ります。
不適切な値を与えると、 ValueError が発生します。
与えた日付が日本において何らかの祝日であれば、その名前が Unicode で返ります。
祝日でない場合は None が返ります。
* 2010/Sep/21
holiday_name() にキーワード引数として datetime.date のオブジェクトも取れる
ようにしました。これを指定する際は年、月、日は指定する必要がなく、指定しても
無視されます。これにより、 jholiday モジュールを使用するスクリプトがすでに
datetime.date のオブジェクトがある場合の効率が若干良くなります。
holiday_name() は、指定した日が祝日であれば
Python 2.x 以前の場合は Unicode 文字列を、
Python 3.x 以降の場合は文字列を
返します。指定した日が祝日でなければ、 Python のバージョンによらず None を返します。
* 2014/May/29
[山の日]改正の修正
* 2015/Nov/30
[ import math ]の記述をコードの先頭に追記
* 2018/Feb/15
[天皇誕生日の変更]改正の修正
* 2018/June/21
5月4日 ( 国民の休日:1986〜2006年 ) 及び 振替休日の判定処理に誤りがありましたので修正しました。
* 2018/June/21
[体育の日⇒スポーツの日 改名] & [五輪特措法による祝日移動(2020年)] 改正の修正
* 2018/July/20
[ import sys ]の記述が抜けていましたので追記しました
* 2018/Dec/8
[即位の日 および 4/30 & 5/2の国民の休日] [即位礼正殿の儀] 改正の修正
* 2020/Nov/28
[五輪特措法による祝日移動(2021年)] 改正の修正
サンプル
Python 2.6.1 (r261:67515, Feb 11 2010, 15:47:53)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import jholiday
>>> jholiday.holiday_name(2007, 4, 28)
None
>>> jholiday.holiday_name(2007, 4, 29)
u'\u662d\u548c\u306e\u65e5'
>>> print jholiday.holiday_name(2007, 4, 29).encode('euc-jp')
昭和の日
>>> import datetime
>>> date = datetime.date(2007, 4, 29)
>>> jholiday.holiday_name(date = date)
u'\u662d\u548c\u306e\u65e5'
Python 3.1.2 (r312:79360M, Mar 24 2010, 01:33:18)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import jholiday
>>> jholiday.holiday_name(2007, 4, 28)
>>> jholiday.holiday_name(2007, 4, 29)
'昭和の日'
>>> print(jholiday.holiday_name(2007, 4, 29))
昭和の日
>>> import datetime
>>> date = datetime.date(2007, 4, 29)
>>> jholiday.holiday_name(date = date)
'昭和の日'
"""
import datetime
import math
import sys
MONDAY, TUESDAY, WEDNESDAY, SUNDAY = 0, 1, 2, 6 # 月(0), 火(1), 水(2), 木(3), 金(4), 土(5), 日(6)
def _vernal_equinox(y):
# 整数で年を与えると、その年の春分の日が3月の何日であるかを返す
if y <= 1947:
d = 99 # 祝日法施行前
elif y <= 1979:
d = math.floor(20.8357 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
elif y <= 2099:
d = math.floor(20.8431 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
elif y <= 2150:
d = math.floor(21.8510 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
else:
d = 99 # 2151年以降は略算式が無いので不明
return d
def _autumn_equinox(y):
# 整数で年を与えると、その年の秋分の日が9月の何日であるかを返す
if y <= 1947:
d = 99 # 祝日法施行前
elif y <= 1979:
d = math.floor(23.2588 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
elif y <= 2099:
d = math.floor(23.2488 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
elif y <= 2150:
d = math.floor(24.2488 + 0.242194 * (y - 1980) - math.floor((y - 1980) / 4))
else:
d = 99 # 2151年以降は略算式が無いので不明
return d
def holiday_name(year = None, month = None, day = None, date = None):
# holiday_name() の呼び出し方法は2通りあります。
#
# 1つ目の方法は、3つの引数 year, month, day に整数を渡す方法です。
# もうひとつの方法は前述のキーワード引数 date に datetime.date のオブジェクトを渡す方法です。
# この場合は year, month, day を渡す必要はなく、また、渡したとしても無視されます。
#
# holiday_name() は、その日が祝日であれば
# Python 2.x 系以前の場合には Unicode 文字列で
# Python 3.x 系以降の場合には文字列で
# 祝日名を返します。
# 指定した日が祝日でなければ、 Python のバージョンによらず None を返します。
# [ date ]引数が省略された場合は [ year, month, day ]引数で日付を作成し [ date ]引数を差し替える。
if date == None:
date = datetime.date(year, month, day)
if date < datetime.date(1948, 7, 20):
return None # 祝日法施行前: None で返す
else:
name = None # name の初期値は None
#-- 1月--
if date.month == 1:
if date.day == 1:
name = '元日'
else:
if date.year >= 2000:
if int((date.day - 1) / 7) == 1 and date.weekday() == MONDAY: # 2nd Monday
name = '成人の日'
else:
if date.day == 15:
name = '成人の日'
#-- 2月 --
elif date.month == 2:
if date.day == 11 and date.year >= 1967:
name = '建国記念の日'
elif date.day == 23 and date.year >= 2020:
name = '天皇誕生日'
elif (date.year, date.month, date.day) == (1989, 2, 24):
name = '昭和天皇の大喪の礼'
#-- 3月 --
elif date.month == 3:
if date.day == _vernal_equinox(date.year): # 1948〜2150以外は[99]が返るので、必ず≠になる
name = '春分の日'
#-- 4月 --
elif date.month == 4:
if date.day == 29:
if date.year >= 2007:
name = '昭和の日'
elif date.year >= 1989:
name = 'みどりの日'
else:
name = '天皇誕生日' # 昭和天皇
elif (date.year, date.month, date.day) == (2019, 4, 30):
name = '国民の休日' # 平成天皇の退位日(祝日ではなく「国民の休日」です)
elif (date.year, date.month, date.day) == (1959, 4, 10):
name = '皇太子明仁親王の結婚の儀'
#-- 5月 --
elif date.month == 5:
if date.day == 3:
name = '憲法記念日'
elif date.day == 4:
if date.year >= 2007:
name = 'みどりの日'
elif (date.year >= 1986) and date.weekday() not in (MONDAY, SUNDAY): # 火曜 以降(火〜土)
# 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年)
name = '国民の休日'
elif date.day == 5:
name = 'こどもの日'
elif date.day == 6:
if date.year >= 2007 and date.weekday() in (TUESDAY, WEDNESDAY): # [5/3,5/4が日曜]ケースのみ、ここで判定
name = '振替休日'
else:
if (date.year, date.month, date.day) == (2019, 5, 1):
name = '即位の日' # 徳仁親王
elif (date.year, date.month, date.day) == (2019, 5, 2):
name = '国民の休日' # 祝日ではなく「国民の休日」です
#-- 6月 --
elif date.month == 6:
if (date.year, date.month, date.day) == (1993, 6, 9):
name = '皇太子徳仁親王の結婚の儀'
#-- 7月 --
elif date.month == 7:
if date.year >= 2022:
if int((date.day - 1) / 7) == 2 and date.weekday() == MONDAY: # 3rd Monday
name = '海の日'
elif date.year == 2021:
# 2021年はオリンピック特措法により
# 「海の日」が 7/22 , 「スポーツの日」が 7/23 に移動
if date.day == 22:
name = '海の日'
elif date.day == 23:
name = 'スポーツの日'
elif date.year == 2020:
# 2020年はオリンピック特措法により
# 「海の日」が 7/23 , 「スポーツの日」が 7/24 に移動
if date.day == 23:
name = '海の日'
elif date.day == 24:
name = 'スポーツの日'
elif date.year >= 2003:
if int((date.day - 1) / 7) == 2 and date.weekday() == MONDAY: # 3rd Monday
name = '海の日'
elif date.year >= 1996:
if date.day == 20:
name = '海の日'
#-- 8月 --
elif date.month == 8:
if date.year >= 2022:
if date.day == 11:
name = '山の日'
elif date.year == 2021:
# 2021年はオリンピック特措法により「山の日」が 8/8 に移動
if date.day == 8:
name = '山の日'
elif date.year == 2020:
# 2020年はオリンピック特措法により「山の日」が 8/10 に移動
if date.day == 10:
name = '山の日'
elif date.year >= 2016:
if date.day == 11:
name = '山の日'
#-- 9月 --
elif date.month == 9:
autumn_equinox = _autumn_equinox(date.year)
if date.day == autumn_equinox: # 1948〜2150以外は[99]が返るので、必ず≠になる
name = '秋分の日'
else:
if date.year >= 2003:
if int((date.day - 1) / 7) == 2 and date.weekday() == MONDAY: # 3rd Monday
name = '敬老の日'
elif date.weekday() == TUESDAY and date.day == autumn_equinox - 1:
name = '国民の休日' # 火曜日&[秋分日の前日]
elif date.year >= 1966 and date.day == 15:
name = '敬老の日'
#-- 10月 --
elif date.month == 10:
if date.year >= 2022:
if int((date.day - 1) / 7) == 1 and date.weekday() == MONDAY: # 2nd Monday
name = 'スポーツの日' # 2020年より改名
elif date.year == 2020 or date.year == 2021:
# 2021年はオリンピック特措法により「スポーツの日」が 7/23 に移動
# 2020年はオリンピック特措法により「スポーツの日」が 7/24 に移動
pass
elif date.year >= 2000:
if int((date.day - 1) / 7) == 1 and date.weekday() == MONDAY: # 2nd Monday
name = '体育の日'
elif (date.year, date.month, date.day) == (2019, 10, 22):
name = '即位礼正殿の儀' # 徳仁親王
elif date.year >= 1966:
if date.day == 10:
name = '体育の日'
#-- 11月 --
elif date.month == 11:
if date.day == 3:
name = '文化の日'
elif date.day == 23:
name = '勤労感謝の日'
elif (date.year, date.month, date.day) == (1990, 11, 12):
name = '即位礼正殿の儀'
#-- 12月 --
elif date.month == 12:
if date.day == 23 and date.year >= 1989 and date.year <= 2018:
name = '天皇誕生日' # 平成天皇
# ----- 振替休日の判定 (振替休日施行日:1973/4/12) -----
# [ 対象日≠祝日/休日 & 対象日=月曜日 ]のみ、前日(=日曜日)を祝日判定する。
# 前日(=日曜日)が祝日の場合は”振替休日”となる。
# 尚、5月6日の扱いを
# 「火曜 or 水曜(みどりの日(5/4) or 憲法記念日(5/3)の振替休日)」⇒5月ブロック内で判定済
# 「月曜(こどもの日(5/5)の振替休日」⇒ここの判定処理で判定
# とする事により、ここでの判定対象は『対象日が月曜日』のみ となります。
#
# name は祝日名 or None (初期値, 祝日ではない場合の値)です。
# 論理演算では「空文字以外の文字列⇒true, 空文字⇒false, None⇒false 」と扱われます。
# [ not name ] は、祝日名が得られた⇒false , 祝日が得られない⇒true となります。
if (not name) and (date.weekday() == MONDAY) and (date >= datetime.date(1973, 4, 12)):
prev = date + datetime.timedelta(days = -1)
if holiday_name(prev.year, prev.month, prev.day):
name = '振替休日'
# holiday_name() は 指定した日が祝日であれば
# Python 2.x 以前の場合は Unicode 文字列を、
# Python 3.x 以降の場合は文字列を
# 返します。指定した日が祝日でなければ Python のバージョンによらず None を返します。
if name and sys.version_info[0] < 3:
name = unicode(name, 'utf-8')
return name # [祝日]等:その名称 , 祝日ではない:None
"""
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
"""