日本红日子的计算

原文提供了VBA、JavaScript、C、C#、Ruby等语言的日本红日子的逻辑实现。 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm

以下是Java的实现版本:

/*
  この Java(J2SE1.4) 用祝日判定コードは、下記ウェブサイトで
  公開されているのVBA用のコードを元に、主にJavascript版と
  C言語版を参考にして
  阿蛭 栄一( ttp://www.age.ne.jp/x/abiru/index.html )が
  編集移植しました。
*/

/*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/
_/ CopyRight(C) K.Tsunoda(AddinBox) 2001 All Rights Reserved.
_/ ( http://www.h3.dion.ne.jp/~sakatsu/index.htm )
_/
_/  この祝日マクロは『kt関数アドイン』で使用しているものです。
_/  このロジックは、レスポンスを第一義として、可能な限り少ない
_/ 【条件判定の実行】で結果を出せるように設計してあります。
_/  この関数では、2003年施行の改正祝日法までをサポートして
_/ います(9月の国民の休日を含む)。
_/
_/ (*1)このマクロを引用するに当たっては、必ずこのコメントも
_/   一緒に引用する事とします。
_/ (*2)他サイト上で本マクロを直接引用する事は、ご遠慮願います。
_/   【 http://www.h3.dion.ne.jp/~sakatsu/holiday_logic.htm 】
_/   へのリンクによる紹介で対応して下さい。
_/ (*3)[ktHolidayName]という関数名そのものは、各自の環境に
_/   おける命名規則に沿って変更しても構いません。
_/ 
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/


import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class KtHoliday{

    private KtHoliday(){
    }

    private static final  Calendar cstImplementTheLawOfHoliday
        = new GregorianCalendar( 1948, Calendar.JULY, 20 );       // 祝日法施行
    private static final  Calendar cstAkihitoKekkon
        = new GregorianCalendar( 1959, Calendar.APRIL, 10 );  // 明仁親王の結婚の儀
    private static final  Calendar cstShowaTaiso
        = new GregorianCalendar( 1989, Calendar.FEBRUARY, 24 );// 昭和天皇大喪の礼
    private static final  Calendar cstNorihitoKekkon
        = new GregorianCalendar( 1993, Calendar.JUNE, 9 );// 徳仁親王の結婚の儀
    private static final  Calendar cstSokuireiseiden
        = new GregorianCalendar( 1990, Calendar.NOVEMBER, 12 );// 即位礼正殿の儀
    private static final  Calendar cstImplementHoliday
        = new GregorianCalendar( 1973, Calendar.APRIL, 12 );// 振替休日施行

    // [prmDate]には "yyyy/m/d"形式の日付文字列を渡す
    public static String getHolidayName( String prmDate ) throws ParseException
    {
        String HolidayName_ret = "";
        SimpleDateFormat formatter = new SimpleDateFormat ( "yyyy/MM/dd" );
        Calendar MyDate = Calendar.getInstance();
        MyDate.setTime( formatter.parse( prmDate ) );
        String HolidayName = prvHolidayChk( MyDate );
        if ( HolidayName == "" ) {
            if ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) {
                // 月曜以外は振替休日判定不要
                if ( MyDate.after( cstImplementHoliday ) || MyDate.equals( cstImplementHoliday ) ) {
                    Calendar YesterDay = (Calendar )MyDate.clone();
                    YesterDay.add( Calendar.DATE, -1 );
                    HolidayName = prvHolidayChk( YesterDay );
                    HolidayName_ret = "";
                    if ( HolidayName != "" ) {
                        HolidayName_ret = "振替休日";
                    } else {
                        HolidayName_ret = "";
                    }
                } else {
                    HolidayName_ret = "";
                }
            } else {
                HolidayName_ret = "";
            }
        } else {
            HolidayName_ret = HolidayName;
        }
        return HolidayName_ret;
    }

    //===============================================================

    private static String prvHolidayChk( Calendar MyDate )
    {
        int NumberOfWeek;
        String Result;
        int MyYear = MyDate.get( Calendar.YEAR );
        int MyMonth = MyDate.get( Calendar.MONTH ) + 1;    // MyMonth:1~12
        int MyDay = MyDate.get( Calendar.DATE );

        if ( MyDate.before( cstImplementTheLawOfHoliday ) ) {
        return ""; // 祝日法施行(1948/7/20 )以前
        } else;

        Result = "";
        switch ( MyMonth ) {
    // 1月 //
        case 1:
            if ( MyDay == 1 ) {
                Result = "元日";
            } else {
                if ( MyYear >= 2000 ) {
                    NumberOfWeek = ( (MyDay - 1 ) / 7 ) + 1;
                    if ( ( NumberOfWeek == 2 ) && ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) ) {
                        Result = "成人の日";
                    } else;
                } else {
                    if ( MyDay == 15 ) {
                        Result = "成人の日";
                    } else;
                }
            }
            break;
    // 2月 //
        case 2:
            if ( MyDay == 11 ) {
                if ( MyYear >= 1967 ) {
                    Result = "建国記念の日";
                } else;
            } else {
                if ( MyDate.equals( cstShowaTaiso ) ) {
                    Result = "昭和天皇の大喪の礼";
                } else;
            }
            break;
    // 3月 //
        case 3:
            if ( MyDay == prvDayOfSpringEquinox( MyYear ) ) {  // 1948~2150以外は[99]
                Result = "春分の日";                       // が返るので、必ず≠になる
            } else;
            break;
    // 4月 //
        case 4:
            if ( MyDay == 29 ) {
                if ( MyYear >= 1989 ) {
                    Result = "みどりの日";
                } else {
                Result = "天皇誕生日";
                }
            } else {
                if ( MyDate.equals( cstAkihitoKekkon ) ) {
                    Result = "皇太子明仁親王の結婚の儀";// ( =1959/4/10 )
                } else;
            }
            break;
    // 5月 //
        case 5:
            if ( MyDay == 3 ) {
                Result = "憲法記念日";
            } else {
                if ( MyDay == 4 ) {
                    if ( MyDate.get( Calendar.DAY_OF_WEEK ) > Calendar.MONDAY ) {
                    // 5/4が日曜日は『只の日曜』、月曜日は『憲法記念日の振替休日』
                        if ( MyYear >= 1986 ) {
                            Result = "国民の休日";
                        } else;
                    } else;
                } else {
                    if ( MyDay == 5 ) {
                        Result = "子供の日";
                    } else;
                }
            }
            break;
    // 6月 //
        case 6:
            if ( MyDate.equals( cstNorihitoKekkon ) ) {
                Result = "皇太子徳仁親王の結婚の儀";
            } else;
            break;
    // 7月 //
        case 7:
            if ( MyYear >= 2003 ) {
                NumberOfWeek = ( (MyDay - 1 ) / 7 ) + 1;
                if ( ( NumberOfWeek == 3 ) && ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) ) {
                    Result = "海の日";
                } else;
            } else {
                if ( MyYear >= 1996 ) {
                    if ( MyDay == 20 ) {
                        Result = "海の日";
                    } else;
                } else;
            }
            break;
    // 9月 //
        case 9:
            //第3月曜日( 15~21 )と秋分日(22~24 )が重なる事はない
            int MyAutumnEquinox = prvDayOfAutumnEquinox( MyYear );
            if ( MyDay == MyAutumnEquinox ) {    // 1948~2150以外は[99]
                Result = "秋分の日";           // が返るので、必ず≠になる
            } else {
                if ( MyYear >= 2003 ) {
                    NumberOfWeek = ( (MyDay - 1 ) / 7 ) + 1;
                    if ( (NumberOfWeek == 3 ) && ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) ) {
                        Result = "敬老の日";
                    } else {
                        if ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.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 = ( ( MyDay - 1 ) / 7 ) + 1;
                if ( (NumberOfWeek == 2 ) && ( MyDate.get( Calendar.DAY_OF_WEEK ) == Calendar.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.equals( cstSokuireiseiden ) ) {
                        Result = "即位礼正殿の儀";
                    } else;
                }
            }
            break;
    // 12月 //
        case 12:
            if ( MyDay == 23 ) {
                if ( MyYear >= 1989 ) {
                    Result = "天皇誕生日";
                } else;
            } else;
            break;
        }

        return Result;
    }

    //===================================================================
    // 春分/秋分日の略算式は
    // 『海上保安庁水路部 暦計算研究会編 新こよみ便利帳』
    // で紹介されている式です。
    private static int prvDayOfSpringEquinox( int MyYear )
    {
        int SpringEquinox_ret;
        if ( MyYear <= 1947 ) {
            SpringEquinox_ret = 99;    //祝日法施行前
        } else {
            if ( MyYear <= 1979 ) {
                SpringEquinox_ret = (int)( 20.8357 + 
                ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1983 ) / 4 ) );
            } else {
                if ( MyYear <= 2099 ) {
                    SpringEquinox_ret = (int)( 20.8431 + 
                    ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1980 ) / 4 ) );
                } else {
                    if ( MyYear <= 2150 ) {
                        SpringEquinox_ret = (int)( 21.851 + 
                        ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1980 ) / 4 ) );
                    } else {
                        SpringEquinox_ret = 99;    //2151年以降は略算式が無いので不明
                    }
                }
            }
        }
        return SpringEquinox_ret;
    }

    //=====================================================================
    private static int prvDayOfAutumnEquinox( int MyYear )
    {
        int AutumnEquinox_ret;
        if ( MyYear <= 1947 ) {
            AutumnEquinox_ret = 99; //祝日法施行前
        } else {
            if ( MyYear <= 1979 ) {
                AutumnEquinox_ret = (int)( 23.2588 + 
                ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1983 ) / 4 ) );
            } else {
                if ( MyYear <= 2099 ) {
                    AutumnEquinox_ret = (int)( 23.2488 + 
                    ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1980 ) / 4 ) );
                } else {
                    if ( MyYear <= 2150 ) {
                        AutumnEquinox_ret = (int)( 24.2488 + 
                        ( 0.242194 * ( MyYear - 1980 ) ) - (int)( (MyYear - 1980 ) / 4 ) );
                    } else {
                        AutumnEquinox_ret = 99;    //2151年以降は略算式が無いので不明
                    }
                }
            }
        }
        return AutumnEquinox_ret;
    }


    /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    _/ 
    _/ ここから先は、阿蛭栄一が独自に追加したコーディングです。
    _/ Thu, 18 Dec 2003 02:25:27 +0900
    _/ [email protected]
    _/ 
    _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

    //=====================================================================

    /*このメソッドは、引数にjava.util.Calendarを取るgetHolidayNameメソッドです。
        単にCalendarオブジェクトから"yyyy/MM/dd"形式の文字列を組み立てて
        getHolidayName( String prmDate )の方のメソッドを呼び出しているだけですが、
        他のアプリケーションからこのクラスを使う時のことを考慮するとString
        ではなく、Calendarを引数に取るメソッドがあった方が便利ですよね?*/
    public static String getHolidayName( Calendar prmDate ) throws ParseException
    {
        SimpleDateFormat f = new SimpleDateFormat ( "yyyy/MM/dd" );
        return getHolidayName( f.format( prmDate.getTime() ) );
    }

    //=====================================================================

    /*このメソッドは動作確認やデバッグ用に用意したメソッドです。
        通常は利用しませんので不要な場合には削除して頂いて結構です。
        使い方は以下の通りです。
        java KtHoliday 1948/01/01 2050/12/30
    */
    public static void main( String args[] ) throws Exception
    {
        SimpleDateFormat f = new SimpleDateFormat ( "yyyy/MM/dd" );
        Calendar current = new GregorianCalendar();
        current.setTime( f.parse( args[0] ) );
        Calendar end = new GregorianCalendar();
        end.setTime( f.parse( args[1] ) );

        String result = "";
        while( current.before( end ) || current.equals( end ) ){
            result = getHolidayName( current );
            if( !result.equals( "" ) ){
                System.out.print( f.format( current.getTime() ) );
                System.out.println( ",\"" + result + "\"" );
            }
            current.add( Calendar.DATE , 1 );
        }

    }
}

猜你喜欢

转载自rensanning.iteye.com/blog/1974340