
VBAおよびVB用の祝日判定用マクロ[関数](『kt関数アドイン/kt祝日名取得』の
ロジックと同じものです)を公開しています。また、VBA用の祝日判定用マクロ[関数]を
基にして、他言語向けに編集移植したコードを頂きましたので、併せて、このページで
公開します。
なお、祝日に関する詳細情報はこちらのページをご覧下さい。
VBA用コードは純粋にVB構文だけ(エクセル独自の機能は使ってません)で作って
ありますので、エクセルだけでなくアクセスや、その他のVBAを使うアプリケーション
でも利用できます。自由に各自のマクロに組み込んで利用して下さい。なお、フリー/シェアソフト
※ 訂正案内 2009/4/30 ※
JAVA の コード において、5月6日の if ブロックで括弧不足がありましたので修正しました。
利用されている方は修正願います。
※ 訂正案内 2009/1/8 ※
Python の コード において、秋分日判定( _autumn_equinox ) で 4つ目の日付条件 が
間違っていました。1979 となっていたのを 2150 に修正しました。
利用されている方は修正願います。
※ 訂正案内 2008/10/29 ※
JavaScript の コード において、var 指定が無く広域変数扱いになっていたのを修正。
利用されている方は修正願います。
※ 訂正案内 2007/11/21 ※
C# の コード において、5月6日に対する判定処理が間違っていました。
利用されている方は修正願います。
※ 訂正案内 2007/5/28 ※
C# , Apollo , Ruby の コード において、1月1日に対して返す祝日名が '元旦' になって
いました。正しくは '元日' ですので、利用されている方は修正願います。
また、C , Perl , AWK の コード において、1月1日の コメント が 元旦 になっていました。
こちらは、フラグ を返す仕様なので処理自体には支障ありません。
上記以外の言語の コード には間違いはありません。
※VBA以外に移植したコードも紹介しています※
下記の コード には 「昭和の日」 改正に伴う 修正 を施してあります。 ( 2005/5/20 )--言語-- -- 移 植 -- -公開日- -頁- 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 〃
開発での利用も可(フリー/シェアでの利用の場合、事後で結構ですので一言
お知らせください)です。ただし、引用に当たっては、マクロの先頭に記述してある
コメント(CopyRight )を必ず一緒に引用する事
を条件とします。
なお、
他サイト上で本マクロを直接引用(マクロ全体を丸々貼り付ける等)
する事は、ご遠慮願います。本ページへのリンクによる紹介で対応して下さい。
[ktHolidayName]という関数名そのものは、各自の環境における命名規則に沿って
変更しても構いません。
VBA(VB含む)で利用する場合はマクロのコード構成を一切変更しないでください。
VBAというレスポンス的に不利な言語でも出来る限りレスポンスを良くする事を前提に
設計してある為、コード内容を変更するとレスポンスが低下する可能性があります。
VBA以外の言語に移植する場合は、その言語の特性に合わせたベストなコード構成に
変更しても構いません。
また、出来上がったものをご連絡頂ければ、このページにて紹介させて貰います。
尚、移植に際しては、And/Orによる条件演算、および[春分の日/秋分の日]算出式の
INT演算について各言語特性に留意して下さい。また、表引き手法を採らない理由も
御一読ください。
[ この場所へのリンク ]
このロジックは、営業日数計算など連続して祝日判定を行なう処理の為に、レスポンス
を第一義として、可能な限り少ない【条件判定の実行】で結果を出せるように設計して
あります(このコードはVBAでの利用を前提にして作っています。同じコードでも、VBでネ
イティブコンパイルした場合と比べれば、VBAは、かなり低速です。そのVBAを使ってい
ても、出来るだけ効率良く高速に処理されるように作ってあります)。
1年間の判定を考えた場合、1年365日の内、祝日は20日ほど、残りの345日ほどは
祝日以外です。したがって、レスポンスを向上させるポイントは『如何に祝日と判定するか』
ではなく、『どれだけ早く祝日でないという判断を下せるか』です。
And条件を使わずに「If文のネスト」にしているのは、この為です。また、一番最初に『月』
による振り分けを行なっている(Select Case文)ので、例えば6月の日付に対して、1月とか
9月とか他の月の条件判定まで実行してしまう事もありません。
(補) VB(VBA)では、And/Or演算子で繋いだ論理演算は完全評価(Complete)型(式の途中で結果が
決まるような条件であっても、最後まで比較演算を実行)ですので、必要の無い判定をスキップさせる
にはAnd/Orを使わずにIf文を分割してネストさせる必要があります。逆に、短絡評価(Short-circuit)型
(And演算では[左辺がFalse なら右辺は評価せずにFalseで決定]、Or演算では[左辺がTrueなら右辺
は評価せずにTrueで決定])の言語ならば、And/Orを使って条件式をスッキリさせるコーディングでも
構いません(短絡評価型かどうかを調べるには、このようなテストを実行すれば確認できます)。
[ この場所へのリンク ]
※ オーソドックスな「表引き」手法との比較 ※
祝日判定処理で従来(現在も)最も使われている手法は『予め祝日の日付をテーブルに用意しておいて、その日付と比較/検索する』というものでしょう。
本ロジックは個々の祝日条件をひとつひとつ判定するように作られていますので、ステップ数としては多くなります。対して「表引き」の場合にはテーブルからの比較/検索で済ませますから、言語の特徴によって、その部分は1〜数ステップで済む筈です。
そうすると、一見、プログラムの大きさから、「表引き」の方が効率的で速いように思えてしまいます。しかし、実際に両者を実行してみると、本ロジックの方が断然速い事が判るでしょう。
何故かというと、プログラムの実行に要する時間は、コーディングされたステップ数の大小によるのではなく、実行の際に処理されるステップ数の大小による からです。
--- 本ロジック の特徴 ---
前述のように
・ And条件を使わずに「If文のネスト」にしている。
・ 一番最初に『月』による振り分けを行なっている。これにより、6月の日付に対して、1月とか9月とか
他の月の条件判定まで実行する事がない。
という特徴で設計してあります。コーディングステップ数は多くても、個々の日付を判定する際に実行されるステップ数は少ないです。更に、平日なら尚更少ない実行ステップで完了します。データ量の9割以上を占めるであろう平日データに対してより速く完了するという事は、データ量が増えれば増える程、より効果を発揮します。また、どの月の日付なら速い/遅いといった事もありませんから、日付の偏りによるパフォーマンスの上下もありません。
--- 表引き の特徴 ---
普通、「祝日」のみのテーブルを用意しますので、判定するにはテーブル内の日付と順々に比較する必要があります。表引きには順次検索/二分検索といった比較方法があり、更に順次検索では「総当り」 か 「大小判定を加えてテーブルの途中で終了」 の2つがありえます。どういった方法が採られるかは配列の言語特性やロジックの作り方によるでしょう。
1年間の祝日をテーブルに用意するならば、20数件ですから、
・ 二分検索では毎回3〜4回
・ 順次検索の場合、
・ 総当りなら毎回20数回(全部見ないと該当日付無しかが判らない)
・ 大小比較付きなら平均10回
の比較処理が実行される事となります。大小比較の場合、日付によって二分検索並みに数回で終わる事も、総当りのように20数回掛かる事もありますので、日付の偏りによってはパフォーマンスが非常に上下する事が想像できます。
言語仕様によっては「処理する日付をキーとしてテーブルに渡して結果を得る」 という検索メソッドの1ステップのコーディングで済んでいる場合もあるでしょうが、言語側の内部では上記と同様のことが実行されていますので、1ステップだから速いという事はありません。
また、1年分ではなく2年分とか数年分といった長期の祝日データを用意すればする程、比較回数は増えてしまいます。特に重要なのは、この比較回数が 祝日/平日に関係なく同じように掛かってしまう事です。例え、平日だけのデータを処理する場合であっても、祝日データが含まれている時よりも早く完了する事は期待できません。
尚、これらの速度的に有利/不利というのは、大量のデータを処理するケースを考えたものです(本ロジックでは [1年間というスパンの営業日数計算を要するデータが1000件] というケースを想定して設計してあります。つまり、祝日判定を36万回連続実行)。
しかし、カレンダーの1ヶ月分のレイアウトを作成するというケースでは「日付が限られた範囲で連続で少量」という点から、表引き手法を用いた祝日判定を用いても何ら問題は無いでしょう。
PS : 「表引き」でも非常に高速で処理する手法はあります。
1年間(365 or 366日分)のテーブルを用意(2年間分なら730 or 731日分)し、1月1日からの通算日を『添字』として各要素に平日/祝日のフラグ、もしくは空文字/祝日名を格納しておきます。処理する日付についても同様に「1月1日からの通算日」に変換し、それを添字としてテーブル内容を取得すれば、毎回1回の比較処理で完了となります。当然、本ロジックよりも速いでしょう。kt関数アドインでは、この手法を使って、より高速化を図っています(年間テーブルの作成には本ロジックを使用しています)。
[ この場所へのリンク ]
[ Note ]
Access などで、[Null値]を受け取る/返すといった必要がある場合には、下記のように
『ktHolidayName 』の外側に、もうひとつ関数を被せるようにする事で『ktHolidayName 』
自体は変更せずに利用する事ができます(この場合には、ktHolidayName は'Private'に
して下さい)。
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祝日には手を加えずに、その外側にプロシ
ジャーを用意して、そこで機能追加を施すようにして下さい。
[ この場所へのリンク ]
MOUG(Access 初級) で回答したので、ここにも載せておきます。 (2004/9/13 追記)
『銀行休日』にするには更に下記のコードを加えると、渡した日付に対して 「銀行休日か否か」が[True/False ]で得られます。 Public Function Bank_Holiday (ByVal 日付 As Date) As Boolean If (ktHolidayName (日付) <> "") Then Bank_Holiday = True '祝日 Else Select Case Weekday(日付) Case vbSunday Bank_Holiday = True Case vbSaturday Bank_Holiday = True Case Else Select Case Format(日付, "mmdd") Case "0102": Bank_Holiday = True '年始 Case "0103": Bank_Holiday = True '年始 Case "1231": Bank_Holiday = True '大晦日 Case Else Bank_Holiday = False End Select End Select End If End Function 銀行休日ベースで営業日を算出するには、更に下記のコードを加えれば、 日付と日数に応じた営業日が出て来ます。[日数=0]の場合には、休日で あっても[日付]がそのまま返ります(WORKDAY と同じ)。 ある日付に対する休日前営/休日翌営の求め方(WORKDAY と同じ)。 休日前営: =Bank_Workday(日付+1, -1) 休日翌営: =Bank_Workday(日付-1, 1) Public Function Bank_Workday (ByVal 日付 As Date, ByVal 日数 As Integer) As Date Dim i As Integer Dim wkStep As Integer Dim wkDate As Date If (日数 = 0) Then Bank_Workday = 日付 Exit Function ElseIf (日数 > 0) Then wkStep = 1 Else wkStep = -1 End If i = 0 wkDate = 日付 Do wkDate = wkDate + wkStep If (Bank_Holiday (wkDate) = False) Then i = i + wkStep End If Loop Until (i = 日数) Bank_Workday = wkDate End Function 営業日数なら下記の関数になります。(2005/2/15 追記) Public Function Bank_Networkdays (ByVal 開始日 As Date, ByVal 終了日 As Date) As Integer Dim wkDate As Date Dim wkStep As Integer Dim int日数 As Integer if (開始日 <= 終了日) Then wkStep = 1 Else wkStep = -1 End If int日数 = 0 For wkDate = 開始日 To 終了日 Step wkStep If (Bank_Holiday (wkDate) = True) Then int日数 = int日数 + wkStep End If Next wkDate Bank_Networkdays = int日数 End Function
【 VB/VBA 用祝日判定コード 】 2005/5/20 [昭和の日]改正の修正
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
Access で「Excel のWorkday/NetWorkdays 関数」と同義のものを組み込む場合はこちら。
『祝日について』
下記コードには「昭和の日」改正に伴う修正を施してありますが、コード上には修正履歴
を残していません。修正の考え方 及び 修正箇所 については こちら を参照。
下記マクロのコメントに記載してある利用規約(*2)の遵守にご協力ください。
Q&Aサイト等での回答に本コードを丸々全部貼り付ける事はお止めください。
特に、先頭のコメント(作者情報/利用規約)を削ってマクロ部分のみ貼り付け
る事(*1への違反)はお止めください。
'_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ '_/ '_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. '_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm ) '_/ '_/ この祝日マクロは『kt関数アドイン』で使用しているものです。 '_/ このロジックは、レスポンスを第一義として、可能な限り少ない '_/ 【条件判定の実行】で結果を出せるように設計してあります。 '_/ この関数では、2007年施行の改正祝日法(昭和の日)までを '_/ サポートしています(9月の国民の休日を含む)。 '_/ '_/ (*1)このマクロを引用するに当たっては、必ずこのコメントも '_/ 一緒に引用する事とします。 '_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。 '_/ 【 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm 】 '_/ へのリンクによる紹介で対応して下さい。 '_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に '_/ おける命名規則に沿って変更しても構いません。 '_/ '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Public Function ktHolidayName(ByVal 日付 As Date) As String Dim dtm日付 As Date Dim str祝日名 As String Const cst振替休日施行日 As Date = "1973/4/12" '時刻/時刻誤差の削除(Now関数などへの対応) dtm日付 = DateSerial(Year(日付), Month(日付), Day(日付)) 'シリアル値は[±0.5秒]の誤差範囲で認識されます。2002/6/21はシリアル値で '[37428.0]ですが、これに[-0.5秒]の誤差が入れば[37427.9999942130]となり、 'Int関数で整数部分を取り出せば[37427]で前日日付になってしまいます。 '※ 但し、引数に指定する値が必ず【手入力した日付】等で、時刻や時刻誤差を ' 考慮しなくても良いならば、このステップは不要です。引数[日付]をそのまま ' 使用しても問題ありません(ほとんどの利用形態ではこちらでしょうが‥‥)。 str祝日名 = prv祝日(dtm日付) If (str祝日名 = "") Then If (Weekday(dtm日付) = vbMonday) Then ' 月曜以外は振替休日判定不要 ' 5/6(火,水)の判定は[prv祝日]で処理済 ' 5/6(月)はここで判定する If (dtm日付 >= cst振替休日施行日) Then str祝日名 = prv祝日(dtm日付 - 1) If (str祝日名 <> "") Then ktHolidayName = "振替休日" Else ktHolidayName = "" End If Else ktHolidayName = "" End If Else ktHolidayName = "" End If Else ktHolidayName = str祝日名 End If End Function '======================================================================== Private Function prv祝日(ByVal 日付 As Date) As String Dim int年 As Integer Dim int月 As Integer Dim int日 As Integer Dim int秋分日 As Integer Dim str第N曜日 As String ' 時刻データ(小数部)は取り除いてあるので、下記の日付との比較はOK Const cst祝日法施行 As Date = "1948/7/20" Const cst昭和天皇の大喪の礼 As Date = "1989/2/24" Const cst明仁親王の結婚の儀 As Date = "1959/4/10" Const cst徳仁親王の結婚の儀 As Date = "1993/6/9" Const cst即位礼正殿の儀 As Date = "1990/11/12" int年 = Year(日付) int月 = Month(日付) int日 = Day(日付) prv祝日 = "" If (日付 < cst祝日法施行) Then Exit Function ' 祝日法施行以前 End If Select Case int月 Case 1 If (int日 = 1) Then prv祝日 = "元日" Else If (int年 >= 2000) Then str第N曜日 = (((int日 - 1) \ 7) + 1) & Weekday(日付) If (str第N曜日 = "22") Then 'Monday:2 prv祝日 = "成人の日" End If Else If (int日 = 15) Then prv祝日 = "成人の日" End If End If End If Case 2 If (int日 = 11) Then If (int年 >= 1967) Then prv祝日 = "建国記念の日" End If ElseIf (日付 = cst昭和天皇の大喪の礼) Then prv祝日 = "昭和天皇の大喪の礼" End If Case 3 If (int日 = prv春分日(int年)) Then ' 1948〜2150以外は[99] prv祝日 = "春分の日" ' が返るので、必ず≠になる End If Case 4 If (int日 = 29) Then If (int年 >= 2007) Then prv祝日 = "昭和の日" ElseIf (int年 >= 1989) Then prv祝日 = "みどりの日" Else prv祝日 = "天皇誕生日" End If ElseIf (日付 = cst明仁親王の結婚の儀) Then prv祝日 = "皇太子明仁親王の結婚の儀" End If Case 5 If (int日 = 3) Then prv祝日 = "憲法記念日" ElseIf (int日 = 4) Then If (int年 >= 2007) Then prv祝日 = "みどりの日" ElseIf (int年 >= 1986) Then ' 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年) If (Weekday(日付) > vbMonday) Then prv祝日 = "国民の休日" End If End If ElseIf (int日 = 5) Then prv祝日 = "こどもの日" ElseIf (int日 = 6) Then If (int年 >= 2007) Then Select Case Weekday(日付) Case vbTuesday, vbWednesday prv祝日 = "振替休日" ' [5/3,5/4が日曜]ケースのみ、ここで判定 End Select End If End If Case 6 If (日付 = cst徳仁親王の結婚の儀) Then prv祝日 = "皇太子徳仁親王の結婚の儀" End If Case 7 If (int年 >= 2003) Then str第N曜日 = (((int日 - 1) \ 7) + 1) & Weekday(日付) If (str第N曜日 = "32") Then 'Monday:2 prv祝日 = "海の日" End If ElseIf (int年 >= 1996) Then If (int日 = 20) Then prv祝日 = "海の日" End If End If Case 9 '第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない int秋分日 = prv秋分日(int年) If (int日 = int秋分日) Then ' 1948〜2150以外は[99] prv祝日 = "秋分の日" ' が返るので、必ず≠になる Else If (int年 >= 2003) Then str第N曜日 = (((int日 - 1) \ 7) + 1) & Weekday(日付) If (str第N曜日 = "32") Then 'Monday:2 prv祝日 = "敬老の日" ElseIf (Weekday(日付) = vbTuesday) Then If (int日 = (int秋分日 - 1)) Then prv祝日 = "国民の休日" End If End If ElseIf (int年 >= 1966) Then If (int日 = 15) Then prv祝日 = "敬老の日" End If End If End If Case 10 If (int年 >= 2000) Then str第N曜日 = (((int日 - 1) \ 7) + 1) & Weekday(日付) If (str第N曜日 = "22") Then 'Monday:2 prv祝日 = "体育の日" End If ElseIf (int年 >= 1966) Then If (int日 = 10) Then prv祝日 = "体育の日" End If End If Case 11 If (int日 = 3) Then prv祝日 = "文化の日" ElseIf (int日 = 23) Then prv祝日 = "勤労感謝の日" ElseIf (日付 = cst即位礼正殿の儀) Then prv祝日 = "即位礼正殿の儀" End If Case 12 If (int日 = 23) Then If (int年 >= 1989) Then prv祝日 = "天皇誕生日" End If End If End Select End Function '====================================================================== ' 春分/秋分日の略算式は ' 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』 ' で紹介されている式です。 Private Function prv春分日(ByVal 年 As Integer) As Integer If (年 <= 1947) Then prv春分日 = 99 '祝日法施行前 ElseIf (年 <= 1979) Then '(年 - 1983)がマイナスになるので『Fix関数』にする prv春分日 = Fix(20.8357 + (0.242194 * (年 - 1980)) - Fix((年 - 1983) / 4)) ElseIf (年 <= 2099) Then prv春分日 = Fix(20.8431 + (0.242194 * (年 - 1980)) - Fix((年 - 1980) / 4)) ElseIf (年 <= 2150) Then prv春分日 = Fix(21.851 + (0.242194 * (年 - 1980)) - Fix((年 - 1980) / 4)) Else prv春分日 = 99 '2151年以降は略算式が無いので不明 End If End Function '======================================================================== Private Function prv秋分日(ByVal 年 As Integer) As Integer If (年 <= 1947) Then prv秋分日 = 99 '祝日法施行前 ElseIf (年 <= 1979) Then '(年 - 1983)がマイナスになるので『Fix関数』にする prv秋分日 = Fix(23.2588 + (0.242194 * (年 - 1980)) - Fix((年 - 1983) / 4)) ElseIf (年 <= 2099) Then prv秋分日 = Fix(23.2488 + (0.242194 * (年 - 1980)) - Fix((年 - 1980) / 4)) ElseIf (年 <= 2150) Then prv秋分日 = Fix(24.2488 + (0.242194 * (年 - 1980)) - Fix((年 - 1980) / 4)) Else prv秋分日 = 99 '2151年以降は略算式が無いので不明 End If End Function '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ '_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
※ 2002/3/28追記(『祝日について』の春分/秋分日の補足説明参照)
VBおよびVBAで『Int関数』を使う場合は、prv春分日/prv秋分日は
下記のようにできます。
Private Function prv春分日(ByVal 年 As Integer) As Integer If (年 <= 1947) Then prv春分日 = 99 '祝日法施行前 ElseIf (年 <= 1979) Then prv春分日 = Int(20.8357 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) ElseIf (年 <= 2099) Then prv春分日 = Int(20.8431 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) ElseIf (年 <= 2150) Then prv春分日 = Int(21.851 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) Else prv春分日 = 99 '2151年以降は略算式が無いので不明 End If End Function '======================================================================== Private Function prv秋分日(ByVal 年 As Integer) As Integer If (年 <= 1947) Then prv秋分日 = 99 '祝日法施行前 ElseIf (年 <= 1979) Then prv秋分日 = Int(23.2588 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) ElseIf (年 <= 2099) Then prv秋分日 = Int(23.2488 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) ElseIf (年 <= 2150) Then prv秋分日 = Int(24.2488 + (0.242194 * (年 - 1980)) - Int((年 - 1980) / 4)) Else prv秋分日 = 99 '2151年以降は略算式が無いので不明 End If End Function
【 Delphi 用祝日判定コード 】 2002/11/22 追記 , 2005/5/20 [昭和の日]改正の修正
上記のVBAコードのロジックを、そのまま[Delphi ]用に書き直したものです。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
『祝日について』
下記コードには「昭和の日」改正に伴う修正を施してありますが、コード上には修正履歴
を残していません。修正の考え方 及び 修正箇所 については こちら を参照。
var function ktHolidayName(MyDate: TDateTime): AnsiString; function prvHolidayChk(MyDate: TDateTime): AnsiString; function prvDayOfSpringEquinox(MyYear: Integer): Integer; function prvDayOfAutumnEquinox(MyYear: Integer): Integer; implementation { _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ _/ _/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. _/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm ) _/ _/ この祝日判定コードは[Excel:kt関数アドイン]で使用している _/ VBAマクロを[Delphi]に移植したものです。 _/ この関数では、2007年施行の改正祝日法(昭和の日)までを _/ サポートしています(9月の国民の休日を含む)。 _/ _/ (1) このコードを引用するに当たっては、必ずこのコメントも _/ 一緒に引用する事とします。 _/ (2) 他サイト上で本マクロを直接引用する事は、ご遠慮願います。 _/ [ http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm ] _/ へのリンクによる紹介で対応して下さい。 _/ (3) [ktHolidayName]という関数名そのものは、各自の環境に _/ おける命名規則に沿って変更しても構いません。 _/ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ } function ktHolidayName(MyDate: TDateTime) : AnsiString; var dtmDate: TDateTime; strHolidayName: AnsiString; begin dtmDate := DateOf(MyDate); // 時刻の削除 strHolidayName := prvHolidayChk(dtmDate); If (strHolidayName = '') then If (DayOfTheWeek(dtmDate) = DayMonday) then // 月曜以外は振替休日判定不要 // 5/6(火,水)の判定はprvHolidayChkで処理済 // 5/6(月)はここで判定する If (dtmDate >= EncodeDate(1973,4,12)) then begin strHolidayName := prvHolidayChk(IncDay(dtmDate, -1)); If (strHolidayName <> '') then Result := '振替休日' else Result := ''; end else Result := '' else Result := '' else Result := strHolidayName; end; //============[祝日判定 本体]============================ function prvHolidayChk(MyDate: TDateTime): AnsiString; var MyYear, MyMonth, MyDay, MyAutumnEquinox: Integer; // [MyDate]からは時刻が取り除いてあるので // 「昭和天皇の大喪の礼」等の日付との比較はOK begin MyYear := YearOf(MyDate); MyMonth := MonthOf(MyDate); MyDay := DayOf(MyDate); Result := ''; If (MyDate < EncodeDate(1948, 7, 20)) then exit; //祝日法施行前 Case MyMonth Of // 1月 // 1:If (MyDay = 1) then Result := '元日' else If (MyYear >= 2000) then If ((((MyDay - 1) div 7) + 1) = 2) and (DayOfTheWeek(MyDate) = DayMonday) then Result := '成人の日' else else If (MyDay = 15) Then Result := '成人の日' else; // 2月 // 2:If (MyDay = 11) then If (MyYear >= 1967) then Result := '建国記念の日' else else If (MyDate = EncodeDate(1989,2,24)) then Result := '昭和天皇の大喪の礼' else; // 3月 // 3:If (MyDay = prvDayOfSpringEquinox(MyYear)) then // 1948〜2150以外は[99] Result := '春分の日' // が返るので、必ず≠になる else; // 4月 // 4:If (MyDay = 29) then Case MyYear of 2007..9999: Result := '昭和の日'; 1989..2006: Result := 'みどりの日'; else Result := '天皇誕生日'; end else If (MyDate = EncodeDate(1959,4,10)) then Result := '皇太子明仁親王の結婚の儀' else; // 5月 // 5:Case MyDay of 3:Result := '憲法記念日'; 4:Case MyYear of 2007..9999: Result := 'みどりの日'; 1986..2006: If (DayOfWeek(MyDate) > 2) then // 日(1),月(2),火(3)...土(7) // 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年) Result := '国民の休日' else else end; 5:Result := 'こどもの日'; 6:If (MyYear >= 2007) then Case DayOfWeek(MyDate) of 3, 4: Result := '振替休日'; // [5/3,5/4が日曜]ケースのみ、ここで判定 else end else; end; // 6月 // 6:If (MyDate = EncodeDate(1993,6,9)) then Result := '皇太子徳仁親王の結婚の儀' else; // 7月 // 7:If (MyYear >= 2003) then If ((((MyDay - 1) div 7) + 1) = 3) and (DayOfTheWeek(MyDate) = DayMonday) then Result := '海の日' else else If (MyYear >= 1996) and (MyDay = 20) then Result := '海の日' else; // 8月(祝日なし) // // 9月(第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない) // 9: begin MyAutumnEquinox := prvDayOfAutumnEquinox(MyYear); If (MyDay = MyAutumnEquinox) then // 1948〜2150以外は[99] Result := '秋分の日' // が返るので、必ず≠になる else If (MyYear >= 2003) Then If ((((MyDay - 1) div 7) + 1) = 3) and (DayOfTheWeek(MyDate) = DayMonday) then Result := '敬老の日' else If (DayOfTheWeek(MyDate) = DayTuesday) and (MyDay = (MyAutumnEquinox - 1)) then Result := '国民の休日' else else If (MyYear >= 1966) and (MyDay = 15) then Result := '敬老の日' else; end; // 10月 // 10: If (MyYear >= 2000) then If ((((MyDay - 1) div 7) + 1) = 2) and (DayOfTheWeek(MyDate) = DayMonday) then Result := '体育の日' else else If (MyYear >= 1966) and (MyDay = 10) Then Result := '体育の日' else; // 11月 // 11: If (MyDay = 3) then Result := '文化の日' else If (MyDay = 23) then Result := '勤労感謝の日' else If (MyDate = EncodeDate(1990,11,12)) then Result := '即位礼正殿の儀' else; // 12月 // 12: If (MyYear >= 1989) and (MyDay = 23) Then Result := '天皇誕生日' else; end end; //================================================================== // 春分/秋分日の略算式は // 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』 // で紹介されている式です。 function prvDayOfSpringEquinox(MyYear: Integer): Integer; begin Case MyYear of 1948..1979: Result := Trunc(20.8357 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1983) / 4)); 1980..2099: Result := Trunc(20.8431 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1980) / 4)); 2100..2150: Result := Trunc(21.851 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1980) / 4)); else Result := 99; // 祝日法施行前および // 2151年以降は略算式が無いので不明 end end; //================================================================= function prvDayOfAutumnEquinox(MyYear: Integer): Integer; begin Case MyYear of 1948..1979: Result := Trunc(23.2588 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1983) / 4)); 1980..2099: Result := Trunc(23.2488 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1980) / 4)); 2100..2150: Result := Trunc(24.2488 + (0.242194 * (MyYear - 1980)) - Int((MyYear - 1980) / 4)); else Result := 99; // 祝日法施行前および // 2151年以降は略算式が無いので不明 end end; // _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ // _/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. // _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
【 JavaScript 用祝日判定コード 】 2003/5/9 追記 , 2005/5/20 [昭和の日]改正の修正
2008/10/29 var 指定が無かったので修正
上記のVBAコードのロジックを、そのまま[Java Script ]用に書き直したものです。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
この[JavaScript]コードは『祝日について』ページの祝日一覧表示ボタンで使っています。
下記コードには「昭和の日」改正に伴う修正を施してありますが、コード上には修正履歴
を残していません。修正の考え方 及び 修正箇所 については こちら を参照。
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //_/ //_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. //_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm ) //_/ //_/ この祝日判定コードは『Excel:kt関数アドイン』で使用している //_/ VBAマクロを[JavaScript]に移植したものです。 //_/ この関数では、2007年施行の改正祝日法(昭和の日)までを //_/ サポートしています(9月の国民の休日を含む)。 //_/ //_/ (*1)このコードを引用するに当たっては、必ずこのコメントも //_/ 一緒に引用する事とします。 //_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。 //_/ 【 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm 】 //_/ へのリンクによる紹介で対応して下さい。 //_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に //_/ おける命名規則に沿って変更しても構いません。 //_/ //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ // 2008/10/29 変数のvar指定が無く、広域変数扱いになっていたのを修正しました。 var MONDAY = 1; var TUESDAY = 2; var WEDNESDAY = 3; // JavaScriptで扱える日付は1970/1/1〜のみ //var cstImplementTheLawOfHoliday = new Date("1948/7/20"); // 祝日法施行 //var cstAkihitoKekkon = new Date("1959/4/10"); // 明仁親王の結婚の儀 var cstShowaTaiso = new Date("1989/2/24"); // 昭和天皇大喪の礼 var cstNorihitoKekkon = new Date("1993/6/9"); // 徳仁親王の結婚の儀 var cstSokuireiseiden = new Date("1990/11/12"); // 即位礼正殿の儀 var cstImplementHoliday = new Date("1973/4/12"); // 振替休日施行 // [prmDate]には "yyyy/m/d"形式の日付文字列を渡す function ktHolidayName(prmDate) { var MyDate = new Date(prmDate); var HolidayName = prvHolidayChk(MyDate); var YesterDay; var HolidayName_ret; if (HolidayName == "") { if (MyDate.getDay() == MONDAY) { // 月曜以外は振替休日判定不要 // 5/6(火,水)の判定はprvHolidayChkで処理済 // 5/6(月)はここで判定する if (MyDate.getTime() >= cstImplementHoliday.getTime()) { YesterDay = new Date(MyDate.getFullYear(), MyDate.getMonth(),(MyDate.getDate()-1)); HolidayName = prvHolidayChk(YesterDay); if (HolidayName != "") { HolidayName_ret = "振替休日"; } else { HolidayName_ret = ""; } } else { HolidayName_ret = ""; } } else { HolidayName_ret = ""; } } else { HolidayName_ret = HolidayName; } return HolidayName_ret; } //=============================================================== function prvHolidayChk(MyDate) { var MyYear = MyDate.getFullYear(); var MyMonth = MyDate.getMonth() + 1; // MyMonth:1〜12 var MyDay = MyDate.getDate(); var Result = ""; var NumberOfWeek; var MyAutumnEquinox; // JavaScriptで扱える日付は1970/1/1〜のみで祝日法施行後なので下記は不要 // if (MyDate.getTime() < cstImplementTheLawOfHoliday.getTime()) { // return ""; // 祝日法施行(1948/7/20)以前 // } else; switch (MyMonth) { // 1月 // case 1: if (MyDay == 1) { Result = "元日"; } else { if (MyYear >= 2000) { NumberOfWeek = Math.floor((MyDay - 1) / 7) + 1; if ((NumberOfWeek == 2) && (MyDate.getDay() == MONDAY)) { Result = "成人の日"; } else; } else { if (MyDay == 15) { Result = "成人の日"; } else; } } break; // 2月 // case 2: if (MyDay == 11) { if (MyYear >= 1967) { Result = "建国記念の日"; } else; } else { if (MyDate.getTime() == cstShowaTaiso.getTime()) { Result = "昭和天皇の大喪の礼"; } else; } break; // 3月 // case 3: if (MyDay == prvDayOfSpringEquinox(MyYear)) { // 1948〜2150以外は[99] Result = "春分の日"; // が返るので、必ず≠になる } else; break; // 4月 // case 4: if (MyDay == 29) { if (MyYear >= 2007) { Result = "昭和の日"; } else { if (MyYear >= 1989) { Result = "みどりの日"; } else { Result = "天皇誕生日"; } } } else { // JavaScriptで扱える日付は1970/1/1〜のみなので下記は不要 // if (MyDate.getTime() == cstAkihitoKekkon.getTime()) { // Result = "皇太子明仁親王の結婚の儀"; // (=1959/4/10) // } else; } break; // 5月 // case 5: switch ( MyDay ) { case 3: // 5月3日 Result = "憲法記念日"; break; case 4: // 5月4日 if (MyYear >= 2007) { Result = "みどりの日"; } else { if (MyYear >= 1986) { if (MyDate.getDay() > MONDAY) { // 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年) Result = "国民の休日"; } else; } else; } break; case 5: // 5月5日 Result = "こどもの日"; break; case 6: // 5月6日 if (MyYear >= 2007) { if ((MyDate.getDay() == TUESDAY) || (MyDate.getDay() == WEDNESDAY)) { Result = "振替休日"; // [5/3,5/4が日曜]ケースのみ、ここで判定 } else; } else; break; } break; // 6月 // case 6: if (MyDate.getTime() == cstNorihitoKekkon.getTime()) { Result = "皇太子徳仁親王の結婚の儀"; } else; break; // 7月 // case 7: if (MyYear >= 2003) { NumberOfWeek = Math.floor((MyDay - 1) / 7) + 1; if ((NumberOfWeek == 3) && (MyDate.getDay() == MONDAY)) { Result = "海の日"; } else; } else { if (MyYear >= 1996) { if (MyDay == 20) { Result = "海の日"; } else; } else; } break; // 9月 // case 9: //第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない MyAutumnEquinox = prvDayOfAutumnEquinox(MyYear); if (MyDay == MyAutumnEquinox) { // 1948〜2150以外は[99] Result = "秋分の日"; // が返るので、必ず≠になる } else { if (MyYear >= 2003) { NumberOfWeek = Math.floor((MyDay - 1) / 7) + 1; if ((NumberOfWeek == 3) && (MyDate.getDay() == MONDAY)) { Result = "敬老の日"; } else { if (MyDate.getDay() == TUESDAY) { if (MyDay == (MyAutumnEquinox - 1)) { Result = "国民の休日"; } else; } else; } } else { if (MyYear >= 1966) { if (MyDay == 15) { Result = "敬老の日"; } else; } else; } } break; // 10月 // case 10: if (MyYear >= 2000) { NumberOfWeek = Math.floor(( MyDay - 1) / 7) + 1; if ((NumberOfWeek == 2) && (MyDate.getDay() == MONDAY)) { Result = "体育の日"; } else; } else { if (MyYear >= 1966) { if (MyDay == 10) { Result = "体育の日"; } else; } else; } break; // 11月 // case 11: if (MyDay == 3) { Result = "文化の日"; } else { if (MyDay == 23) { Result = "勤労感謝の日"; } else { if (MyDate.getTime() == cstSokuireiseiden.getTime()) { Result = "即位礼正殿の儀"; } else; } } break; // 12月 // case 12: if (MyDay == 23) { if (MyYear >= 1989) { Result = "天皇誕生日"; } else; } else; break; } return Result; } //=================================================================== // 春分/秋分日の略算式は // 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』 // で紹介されている式です。 function prvDayOfSpringEquinox(MyYear) { var SpringEquinox_ret; if (MyYear <= 1947) { SpringEquinox_ret = 99; //祝日法施行前 } else { if (MyYear <= 1979) { // Math.floor 関数は[VBAのInt関数]に相当 SpringEquinox_ret = Math.floor(20.8357 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { if (MyYear <= 2099) { SpringEquinox_ret = Math.floor(20.8431 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { if (MyYear <= 2150) { SpringEquinox_ret = Math.floor(21.851 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { SpringEquinox_ret = 99; //2151年以降は略算式が無いので不明 } } } } return SpringEquinox_ret; } //===================================================================== function prvDayOfAutumnEquinox(MyYear) { var AutumnEquinox_ret; if (MyYear <= 1947) { AutumnEquinox_ret = 99; //祝日法施行前 } else { if (MyYear <= 1979) { // Math.floor 関数は[VBAのInt関数]に相当 AutumnEquinox_ret = Math.floor(23.2588 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { if (MyYear <= 2099) { AutumnEquinox_ret = Math.floor(23.2488 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { if (MyYear <= 2150) { AutumnEquinox_ret = Math.floor(24.2488 + (0.242194 * (MyYear - 1980)) - Math.floor((MyYear - 1980) / 4)); } else { AutumnEquinox_ret = 99; //2151年以降は略算式が無いので不明 } } } } return AutumnEquinox_ret; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved. //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
※[春分日/秋分日]算出式の『1979年以前』のコードが、VBAやC言語のコードと異なる
理由はこちらの解説をご覧下さい。
JavaScriptの[ Math.floor 関数]では【 Math.floor( -8.4 ) → -9 】です。
----- [ Java Script ]用の実行サンプルHTML -------
上記のコードを下記の部分にコピーして使って下さい。
<HTML> <HEAD> <TITLE></TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- 【この場所に 上記のJavaScriptコードを貼り付けます】 var WeekName = new Array(7); WeekName[0] = "日"; WeekName[1] = "月"; WeekName[2] = "火"; WeekName[3] = "水"; WeekName[4] = "木"; WeekName[5] = "金"; WeekName[6] = "土"; function getWeekName(Week) { // 曜日の日本語名変換 return WeekName[Week]; } function sample1() { document.Form1.TextBox2.value = ktHolidayName(document.Form1.TextBox1.value); } function sample2() { var OneDay = 24 * 60 * 60 * 1000; // 1日をミリ秒で表現 var FirstDate = new Date("1970/1/1"); var LastDate = new Date("2051/1/1"); var wkDate = FirstDate; var strDate; var HName; while (wkDate.getTime() < LastDate.getTime()) { strDate = wkDate.getFullYear() + "/" + (wkDate.getMonth() + 1) + "/" + wkDate.getDate(); HName = ktHolidayName(strDate); if (HName != "") { document.write(strDate + "(" + getWeekName(wkDate.getDay()) + ")" + HName + "<BR>"); } wkDate.setTime(wkDate.getTime() + OneDay); } } //--> </SCRIPT> </HEAD> <BODY> 日付を yyyy/mm/dd 形式で入力して変換ボタンをクリック<BR> <FORM name="Form1"> <INPUT size="20" type="text" name="TextBox1"> <INPUT type="button" name="Button1" value="→祝日名変換→" onclick="sample1();"> <INPUT size="20" type="text" name="TextBox2"><BR><BR> 1970/1/1〜2050/12/31の期間の祝日一覧を表示<BR> <INPUT type="button" name="Button2" value="1970〜2050年の祝日一覧" onclick="sample2();"> </FORM> </BODY> </HTML>---------------------------------------------------------------------
All About Japan[ JavaScript ]( 高橋 登史朗さん )で紹介されている、
JavaScriptによる日付入力ポップアップフォーム に、
上記ロジックによる「祝日表示 他」の修正を加えたものを こちら で、ご覧頂けます。(2004/7/9 追記)
【 OpenOffice.org Basic 用祝日判定コード 】 2005/4/15 追記 , 2005/5/20 [昭和の日]改正の修正
上記のVBAコードのロジックを、そのまま[OpenOffice.org Basic ]用に書き直したものです(英語版)。
VBAとの違いによる変更点は下記になります。
(1) 変数名等に日本語名が使えない
(2) vbMonday等のVB定数に相当するものが無いので、Constant を用意
(3) 定数定義において["]で囲んだ日付文字列で指定すると、極端に実行速度が落ちた為、
[#]で囲んだ日付リテラルによる指定に変更
#1959/4/10# という日付リテラル形式が OOoBasic では単なる割り算と解釈(=48.975)
される為、シリアル値(21650)で定数定義するように変更
(4) [Private]を指定しても無視されてマクロダイアログに現れる為、
prv祝日/prv春分日/prv秋分日を独立させずに全てktHolidayNameにまとめる
(5) (4)の変更に伴い、振替休日判定をルーチン内の最後に配置し、
再帰呼出方式により実行する
逆に、この OOoBasic 用コードは、そのまま何も修正する事無く VBA で動作します。
土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
『祝日について』
下記コードには「昭和の日」改正に伴う修正を施してありますが、コード上には修正履歴
を残していません。修正の考え方 及び 修正箇所 については こちら を参照。
'_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ '_/ '_/ CopyRight(C) K.Tsunoda(AddinBox) 2005 All Rights Reserved. '_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm ) '_/ '_/ この祝日判定コードは『Excel:kt関数アドイン』で使用している '_/ VBAマクロを[OpenOffice.org Basic]に移植したものです。 '_/ このロジックは、レスポンスを第一義として、可能な限り少ない '_/ 【条件判定の実行】で結果を出せるように設計してあります。 '_/ この関数では、2007年施行の改正祝日法(昭和の日)までを '_/ サポートしています(9月の国民の休日を含む)。 '_/ '_/ (*1)このマクロを引用するに当たっては、必ずこのコメントも '_/ 一緒に引用する事とします。 '_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。 '_/ 【 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm 】 '_/ へのリンクによる紹介で対応して下さい。 '_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に '_/ おける命名規則に沿って変更しても構いません。 '_/ '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Function ktHolidayName(ByVal ChkDate As Date) As String Dim strHoliday As String Dim intYear As Integer Dim intMonth As Integer Dim intDay As Integer Dim intSpringEquinox As Integer Dim intAutumnEquinox As Integer Dim strWeek As String Const cstMonday As Integer = 2 Const cstTuesday As Integer = 3 Const cstWednesday As Integer = 4 Const cstImplementTheLawOfHoliday As Date = 17734 '祝日法施行(1948/7/20) Const cstImplementHolidayInLieu As Date = 26766 '振替休日施行(1973/4/12) Const cstShowaTaiso As Date = 32563 '昭和天皇の大喪の礼(1989/2/24) Const cstAkihitoKekkon As Date = 21650 '明仁親王の結婚の儀(1959/4/10) Const cstNorihitoKekkon As Date = 34129 '徳仁親王の結婚の儀(1993/6/9) Const cstSokuireiSeiden As Date = 33189 '即位礼正殿の儀(1990/11/12) intYear = Year(ChkDate) intMonth = Month(ChkDate) intDay = Day(ChkDate) strHoliday = "" If (ChkDate < cstImplementTheLawOfHoliday) Then ktHolidayName = "" ' 祝日法施行以前 Exit Function End If Select Case intMonth Case 1 If (intDay = 1) Then strHoliday = "元日" Else If (intYear >= 2000) Then strWeek = (((intDay - 1) \ 7) + 1) & Weekday(ChkDate) If (strWeek = "22") Then '第2月曜(Monday:2) strHoliday = "成人の日" End If Else If (intDay = 15) Then strHoliday = "成人の日" End If End If End If Case 2 If (intDay = 11) Then If (intYear >= 1967) Then strHoliday = "建国記念の日" End If ElseIf (ChkDate = cstShowaTaiso) Then strHoliday = "昭和天皇の大喪の礼" End If Case 3 '春分/秋分日の略算式は『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』 'で紹介されている式です。 If (intYear <= 1947) Then intSpringEquinox = 99 '祝日法施行前 ElseIf (intYear <= 1979) Then '(年 - 1983)がマイナスになるので『Fix関数』にする intSpringEquinox = Fix(20.8357 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1983) / 4)) ElseIf (intYear <= 2099) Then intSpringEquinox = Fix(20.8431 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1980) / 4)) ElseIf (intYear <= 2150) Then intSpringEquinox = Fix(21.851 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1980) / 4)) Else intSpringEquinox = 99 ' 2151年以降は略算式が無いので不明 End If If (intDay = intSpringEquinox) Then ' 1948〜2150以外は[99] strHoliday = "春分の日" ' が返るので、必ず≠になる End If Case 4 If (intDay = 29) Then If (intYear >= 2007) Then strHoliday = "昭和の日" ElseIf (intYear >= 1989) Then strHoliday = "みどりの日" Else strHoliday = "天皇誕生日" End If ElseIf (ChkDate = cstAkihitoKekkon) Then strHoliday = "皇太子明仁親王の結婚の儀" End If Case 5 If (intDay = 3) Then strHoliday = "憲法記念日" ElseIf (intDay = 4) Then If (intYear >= 2007) Then strHoliday = "みどりの日" ElseIf (intYear >= 1986) Then ' 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』(〜2006年) If (Weekday(ChkDate) > cstMonday) Then strHoliday = "国民の休日" End If End If ElseIf (intDay = 5) Then strHoliday = "こどもの日" ElseIf (intDay = 6) Then If (intYear >= 2007) Then Select Case Weekday(ChkDate) Case cstTuesday, cstWednesday strHoliday = "振替休日" ' [5/3,5/4が日曜]ケースのみ、ここで判定 End Select End If End If Case 6 If (ChkDate = cstNorihitoKekkon) Then strHoliday = "皇太子徳仁親王の結婚の儀" End If Case 7 If (intYear >= 2003) Then strWeek = (((intDay - 1) \ 7) + 1) & Weekday(ChkDate) If (strWeek = "32") Then '第3月曜日(Monday:2) strHoliday = "海の日" End If ElseIf (intYear >= 1996) Then If (intDay = 20) Then strHoliday = "海の日" End If End If Case 9 '秋分日の略算式は『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』 'で紹介されている式です。 If (intYear <= 1947) Then intAutumnEquinox = 99 '祝日法施行前 ElseIf (intYear <= 1979) Then '(年 - 1983)がマイナスになるので『Fix関数』にする intAutumnEquinox = Fix(23.2588 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1983) / 4)) ElseIf (intYear <= 2099) Then intAutumnEquinox = Fix(23.2488 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1980) / 4)) ElseIf (intYear <= 2150) Then intAutumnEquinox = Fix(24.2488 + (0.242194 * (intYear - 1980)) - Fix((intYear - 1980) / 4)) Else intAutumnEquinox = 99 ' 2151年以降は略算式が無いので不明 End If '第3月曜日(15〜21)と秋分日(22〜24)が重なる事はない If (intDay = intAutumnEquinox) Then ' 1948〜2150以外は[99] strHoliday = "秋分の日" ' が返るので、必ず≠になる Else If (intYear >= 2003) Then strWeek = (((intDay - 1) \ 7) + 1) & Weekday(ChkDate) If (strWeek = "32") Then '第3月曜日(Monday:2) strHoliday = "敬老の日" ElseIf (Weekday(ChkDate) = cstTuesday) Then If (intDay = (intAutumnEquinox - 1)) Then strHoliday = "国民の休日" End If End If ElseIf (intYear >= 1966) Then If (intDay = 15) Then strHoliday = "敬老の日" End If End If End If Case 10 If (intYear >= 2000) Then strWeek = (((intDay - 1) \ 7) + 1) & Weekday(ChkDate) If (strWeek = "22") Then '第2月曜日(Monday:2) strHoliday = "体育の日" End If ElseIf (intYear >= 1966) Then If (intDay = 10) Then strHoliday = "体育の日" End If End If Case 11 If (intDay = 3) Then strHoliday = "文化の日" ElseIf (intDay = 23) Then strHoliday = "勤労感謝の日" ElseIf (ChkDate = cstSokuireiSeiden) Then strHoliday = "即位礼正殿の儀" End If Case 12 If (intDay = 23) Then If (intYear >= 1989) Then strHoliday = "天皇誕生日" End If End If End Select ' 【振替休日の判定】 If (strHoliday = "") Then If (Weekday(ChkDate) = cstMonday) Then ' 月曜以外は振替休日判定不要 ' 5/6(火,水)の判定は上記ステップで処理済 ' 5/6(月)はここで判定する If (ChkDate >= cstImplementHolidayInLieu) Then If (ktHolidayName(ChkDate - 1) <> "") Then '再帰呼出(月曜のみ) ktHolidayName = "振替休日" Else ktHolidayName = "" End If Else ktHolidayName = "" End If Else ktHolidayName = "" End If Else ktHolidayName = strHoliday End If End Function '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ '_/ CopyRight(C) K.Tsunoda(AddinBox) 2005 All Rights Reserved. '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 以下はテストマクロです。 Sub Test dim MyDate as date dim dtmStart as date dim dtmEnd as date dim strwk1 as string dim strwk2 as string const cstYear as integer = 2005 dtmStart = dateserial(cstYear,1,1) dtmEnd = dateserial(cstYear,12,31) for MyDate = dtmStart to dtmEnd step 1 strwk1 = ktHolidayName(MyDate) if (strwk1 <> "") then strwk2 = strwk2 & Chr(13) & Format(MyDate,"yyyy/mm/dd") & "(" & _ Choose(Weekday(MyDate),"日","月","火","水","木","金","土") & _ ") , " & strwk1 end if next MyDate Beep MsgBox strwk2 End Sub
![]()