【 2016年9月15日  サイト 移転のお知らせ 】
      AddinBox サイトを [ DION ] から [ さくら インターネット ] へ移転しました。  なお、旧サイト は 2017年10月 まで残します。
      この ページ の 移転先 URL  ⇒⇒  http://addinbox.sakura.ne.jp/holiday_logic.htm  
 

AddinBox(Title_Logo)

  -- Page 1 --
      VBAおよびVB用の祝日判定用マクロ[関数](『kt関数アドイン/kt祝日名取得』の
  ロジックと同じものです)を公開しています。また、VBA用の祝日判定用マクロ[関数]を
  基にして、他言語向けに編集移植したコードを頂きましたので、併せて、このページで
  公開します。

      なお、祝日に関する詳細情報こちらのページをご覧下さい。

      VBA用コードは純粋にVB構文だけ(エクセル独自の機能は使ってません)で作って
    ありますので、エクセルだけでなくアクセスや、その他のVBAを使うアプリケーション
    でも利用できます。
  ※ 重要 ※
    ・ [ 山の日:8月11日 ] の祝日法改正案が成立しました。 (H26/5/23)
       2016年(平成28年) から施行です。

 
  ※ 訂正案内 2016/3/5 ※
    応用例の Bank_Networkdays 関数に誤りがありました。
    If 文の True/False を取り違えていたため、営業日数 ではなく
    [休業]日数 を算出する ロジック となっていました。




※VBA以外に移植したコードも紹介しています※
 ・ 下記の全ての コード は 「山の日」 祝日改正への対応済みです。(2014/5/29)
 ・ 「昭和の日」 に伴う 「振替休日(5/6)」 改正への 修正方針 もお読みください。 ( 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

ActionScript 3 stocksrc.com  2010/ 3/23 6
Go 言語 杉田 臣輔 さん 2015/ 1/ 6
       
      自由に各自のマクロに組み込んで利用して下さい。なお、フリー/シェアソフト
    開発での利用も可(フリー/シェアでの利用の場合、事後で結構ですので一言
    お知らせください)です。ただし、引用に当たっては、マクロの先頭に記述してある
        コメント(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 追記)

 ※※ 訂正案内 ※※    ( 2016/3/5 )
    ここで紹介している応用例の Bank_Networkdays 関数に誤りがありました
    If 文の True/False を取り違えていたため、営業日数 ではなく
    [休業]日数 を算出する ロジック となっていました。



  『銀行休日』にするには更に下記のコードを加えると、渡した日付に対して
  「銀行休日か否か」が[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
-- 算出例 (分析ツールの WORKDAY関数と同じです) --
    〔日数=   1〕 …… 「日付」の翌営業日
    〔日数=−1〕 …… 「日付」の前営業日
    〔日数=   0〕 …… 「日付」の当日(休業日でも)


  営業日数なら下記の関数になります。(2005/2/15 追記)

  ( 訂正案内  2016/3/5 )
      If 文の True/False を取り違えていたため、営業日数 ではなく
      [休業]日数 を算出する ロジック となっていました。

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) = False) Then  '2016/3/5 修正 (誤)True⇒(正)False
      int日数 = int日数 + wkStep
    End If
  Next wkDate
  Bank_Networkdays = int日数
End Function
-- 算出例 (分析ツールの NETWORKDAYS関数と同じです) --
    〔終了日=開始日         〕 …… 1(開始日が休業日の場合は 0 )
    〔終了日=開始日の翌営〕 …… 2(開始日が休業日の場合は 1 )
    〔終了日=開始日の前営〕 …… −2(開始日が休業日の場合は −1 )



[ この場所へのリンク ]  [ サイト移転のお知らせ ]

VB/VBA 用祝日判定コード 】  2005/5/20 [昭和の日]改正の修正 , 2014/5/29 [山の日]改正の修正
    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
    Access で「Excel のWorkday/NetWorkdays 関数」と同義のものを組み込む場合はこちら
    『祝日について

    「昭和の日」に伴う「振替休日(5月6日)」改正への修正方針もお読みください。

   下記マクロのコメントに記載してある利用規約(*2)の遵守にご協力ください。
   Q&Aサイト等での回答に本コードを丸々全部貼り付ける事はお止めください。
   特に、先頭のコメント(作者情報/利用規約)を削ってマクロ部分のみ貼り付け
   る事(*1への違反)はお止めください。



'_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
'_/
'_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
'_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm )
'_/
'_/  この祝日マクロは『kt関数アドイン』で使用しているものです。
'_/  このロジックは、レスポンスを第一義として、可能な限り少ない
'_/   【条件判定の実行】で結果を出せるように設計してあります。
'_/  この関数では、2016年施行の改正祝日法(山の日)までを
'_/   サポートしています。
'_/
'_/ (*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 8
        If (int日 = 11) Then
            If (int年 >= 2016) 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 [昭和の日]改正の修正
                                                      2014/5/29 [山の日]改正の修正

    上記のVBAコードのロジックを、そのまま[Delphi ]用に書き直したものです。
    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
    『祝日について

    「昭和の日」に伴う「振替休日(5月6日)」改正への 修正方針 もお読みください。



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]に移植したものです。
_/  この関数では、2016年施行の改正祝日法(山の日)までを
_/  サポートしています。
_/
_/ (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月 //
    8: If (MyYear >= 2016) and (MyDay = 11) Then
          Result := '山の日'
        else;
  // 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 指定が無かったので修正
                                                            2011/3/20 [FireFox TraceMonkey バグ]対応で修正
                                                            2014/5/29 [山の日]改正の修正
                                                            2015/7/11 [1970/1/1 以降のみ可]の制限を解除

    上記のVBAコードのロジックを、そのまま[Java Script ]用に書き直したものです。
    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
    この[JavaScript]コードは『祝日について』ページの祝日一覧表示ボタンで使っています。

    ※ ご案内 ※ (2014/5/29)
            2011/3 頃、FireFox 3.5/3.6 のバグにより、祝日判定スクリプトが誤判定 (switch ステートメント への JITコン
            パイル不具合が原因) をする場合がありました。 尚、スクリプト自体に間違いはありませんので、IE , Opera 等
            の FireFox 以外のブラウザでは全く問題はありませんでした。 この件への対応の為、2011/3〜2014/5 の期間、
            if ステートメント による コード を掲載してきましたが、既に FireFox の バグ修正も完了しており、それから大分
            経っていますので、「山の日」 祝日改正への修正の際に switch ステートメントによるコードへ戻します
            この不具合の詳細、および FireFox のバグ対応経緯については下記を参照してください。
               [ FireFox_TMBug_Test.htm ]  (2011/6/22 FireFox 5.0 で修正されました)
                FireFox5.0 Bug Fixes ( 620757 TM:don't trace JSOP_TABLESWITCH )

    JavaScript ファイル(下記) : HolidayChk.js  ,  [ if ステートメント 版 : HolidayChk_IF.js ]

    「昭和の日」に伴う「振替休日(5月6日)」改正への 修正方針 もお読みください。


<!--
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/
//_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
//_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm )
//_/
//_/ この祝日判定コードは『Excel:kt関数アドイン』で使用している
//_/ VBAマクロを[JavaScript]に移植したものです。
//_/ この関数では、2016年施行の改正祝日法(山の日)までを
//_/ サポートしています。
//_/
//_/ (*1)このコードを引用するに当たっては、必ずこのコメントも
//_/ 一緒に引用する事とします。
//_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
//_/ 【 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm 】
//_/ へのリンクによる紹介で対応して下さい。
//_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に
//_/ おける命名規則に沿って変更しても構いません。
//_/ 
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//
// 2008/10/29 変数のvar指定が無く、広域変数扱いになっていたのを修正しました。
//
// 2014/5/29 「山の日」の祝日法改正
//
// 2015/7/11  JavaScript1.3 以降では[1970/1/1]以前も扱えるため、日付範囲の制限を解除


var MONDAY = 1;
var TUESDAY = 2;
var WEDNESDAY = 3;

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 NumberOfWeek;
  var MyAutumnEquinox;

  var Result = "";

  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 {
           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;
// 8月 //
  case 8:
      if (MyDay == 11) {
          if (MyYear >= 2016) {
              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 [昭和の日]改正の修正
                                                                                2014/5/29 [山の日]改正の修正

    上記の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 で動作します。

    土日なども一緒に判定するなど条件を付加する場合は、こちらの解説を参考にして下さい。
    『祝日について

    「昭和の日」に伴う「振替休日(5月6日)」改正への 修正方針 もお読みください。


'_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
'_/
'_/ CopyRight(C) K.Tsunoda(AddinBox) 2005 All Rights Reserved.
'_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm )
'_/
'_/  この祝日判定コードは『Excel:kt関数アドイン』で使用している
'_/  VBAマクロを[OpenOffice.org Basic]に移植したものです。
'_/ このロジックは、レスポンスを第一義として、可能な限り少ない
'_/ 【条件判定の実行】で結果を出せるように設計してあります。
'_/ この関数では、2016年施行の改正祝日法(山の日)までを
'_/ サポートしています。
'_/
'_/ (*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 8
        If (intDay = 11) Then
            If (intYear >= 2016) 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






角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved.