日本红日子的计算

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

以下是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
_/ abiru@home.104.net
_/
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

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

/*このメソッドは、引数に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 );
}

}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1JAVA SE 1.1深入JAVA API 1.1.1Lang包 1.1.1.1String类和StringBuffer类 位于java.lang包中,这个包中的类使用时不用导入 String类一旦初始化就不可以改变,而stringbuffer则可以。它用于封装内容可变的字符串。它可以使用tostring()转换成string字符串。 String x=”a”+4+”c”编译时等效于String x=new StringBuffer().append(“a”).append(4).append(“c”).toString(); 字符串常量是一种特殊的匿名对象,String s1=”hello”;String s2=”hello”;则s1==s2;因为他们指向同一个匿名对象。 如果String s1=new String(“hello”);String s2=new String(“hello”);则s1!=s2; /*逐行读取键盘输入,直到输入为“bye”时,结束程序 注:对于回车换行,在windows下面,有'\r'和'\n'两个,而unix下面只有'\n',但是写程序的时候都要把他区分开*/ public class readline { public static void main(String args[]) { String strInfo=null; int pos=0; byte[] buf=new byte[1024];//定义一个数组,存放换行前的各个字符 int ch=0; //存放读入的字符 system.out.println(“Please input a string:”); while(true) { try { ch=System.in.read(); //该方法每次读入一个字节的内容到ch变量中。 } catch(Exception e) { } switch(ch) { case '\r': //回车时,不进行处理 break; case '\n': //换行时,将数组总的内容放进字符串中 strInfo=new String(buf,0,pos); //该方法将数组中从第0个开始,到第pos个结束存入字符串。 if(strInfo.equals("bye")) //如果该字符串内容为bye,则退出程序。 { return; } else //如果不为bye,则输出,并且竟pos置为0,准备下次存入。 { System.out.println(strInfo); pos=0; break; } default: buf[pos++]=(byte)ch; //如果不是回车,换行,则将读取的数据存入数组中。 } } } } String类的常用成员方法 1、构造方法: String(byte[] byte,int offset,int length);这个在上面已经用到。 2、equalsIgnoreCase:忽略大小写的比较,上例中如果您输入的是BYE,则不会退出,因为大小写不同,但是如果使用这个方法,则会退出。 3、indexOf(int ch);返回字符ch在字符串中首次出现的位置 4、substring(int benginIndex); 5、substring(int beginIndex,int endIndex); 返回字符串的子字符串,4返回从benginindex位置开始到结束的子字符串,5返回beginindex和endindex-1之间的子字符串。 基本数据类型包装类的作用是:将基本的数据类型包装成对象。因为有些方法不可以直接处理基本数据类型,只能处理对象,例如vector的add方法,参数就只能是对象。这时就需要使用他们的包装类将他们包装成对象。 例:在屏幕上打印出一个*组成的矩形,矩形的宽度和高度通过启动程序时传递给main()方法的参数指定。 public class testInteger { public static void main(String[] args) //main()的参数是string类型的数组,用来做为长,宽时,要转换成整型。 { int w=new Integer(args[0]).intValue(); int h=Integer.parseInt(args[1]); //int h=Integer.valueOf(args[1]).intValue(); //以上为三种将字符串转换成整形的方法。 for(int i=0;i<h;i++) { StringBuffer sb=new StringBuffer(); //使用stringbuffer,是因为它是可追加的。 for(int j=0;j<w;j++) { sb.append('*'); } System.out.println(sb.toString()); //在打印之前,要将stringbuffer转化为string类型。 } } } 比较下面两段代码的执行效率: (1)String sb=new String(); For(int j=0;j<w;j++) { Sb=sb+’*’; } (2) StringBuffer sb=new StringBuffer(); For(int j=0;j<w;j++) { Sb.append(‘*’); } (1)和(2)在运行结果上相同,但效率相差很多。 (1)在每一次循环中,都要先将string类型转换为stringbuffer类型,然后将‘*’追加进去,然后再调用tostring()方法,转换为string类型,效率很低。 (2)在没次循环中,都只是调用原来的那个stringbuffer对象,没有创建新的对象,所以效率比较高。 1.1.1.2System类与Runtime类 由于java不支持全局函数和全局变量,所以java设计者将一些与系统相关的重要函数和变量放在system类中。 我们不能直接创建runtime的实例,只能通过runtime.getruntime()静态方法来获得。 编程实例:在java程序中启动一个windows记事本程序的运行实例,并在该运行实例中打开该运行程序的源文件,启动的记事本程序5秒后关闭。 public class Property { public static void main(String[] args) { Process p=null; //java虚拟机启动的进程。 try { p=Runtime.getRuntime().exec("notepad.exe Property.java"); //启动记事本并且打开源文件。 Thread.sleep(5000); //持续5秒 p.destroy(); //关闭该进程 } catch(Exception ex) { ex.printStackTrace(); } } } 1.1.1.3Java语言中两种异常的差别 Java提供了两类主要的异常:runtime exception和checked exception。所有的checked exception是从java.lang.Exception类衍生出来的,而runtime exception则是从java.lang.RuntimeException或java.lang.Error类衍生出来的。    它们的不同之处表现在两方面:机制上和逻辑上。    一、机制上    它们在机制上的不同表现在两点:1.如何定义方法;2. 如何处理抛出的异常。请看下面CheckedException的定义:    public class CheckedException extends Exception    {    public CheckedException() {}    public CheckedException( String message )    {    super( message );    }    }    以及一个使用exception的例子:    public class ExceptionalClass    {    public void method1()    throws CheckedException    {     // ... throw new CheckedException( “...出错了“ );    }    public void method2( String arg )    {     if( arg == null )     {      throw new NullPointerException( “method2的参数arg是null!” );     }    }    public void method3() throws CheckedException    {     method1();    }    }    你可能已经注意到了,两个方法method1()和method2()都会抛出exception,可是只有method1()做了声明。另外,method3()本身并不会抛出exception,可是它却声明会抛出CheckedException。在向你解释之前,让我们先来看看这个类的main()方法:    public static void main( String[] args )    {    ExceptionalClass example = new ExceptionalClass();    try    {    example.method1();    example.method3();    }    catch( CheckedException ex ) { } example.method2( null );    }    在main()方法中,如果要调用method1(),你必须把这个调用放在try/catch程序块当中,因为它会抛出Checked exception。    相比之下,当你调用method2()时,则不需要把它放在try/catch程序块当中,因为它会抛出的exception不是checked exception,而是runtime exception。会抛出runtime exception的方法在定义时不必声明它会抛出exception。    现在,让我们再来看看method3()。它调用了method1()却没有把这个调用放在try/catch程序块当中。它是通过声明它会抛出method1()会抛出的exception来避免这样做的。它没有捕获这个exception,而是把它传递下去。实际上main()方法也可以这样做,通过声明它会抛出Checked exception来避免使用try/catch程序块(当然我们反对这种做法)。    小结一下:    * Runtime exceptions:    在定义方法时不需要声明会抛出runtime exception;    在调用这个方法时不需要捕获这个runtime exception;    runtime exception是从java.lang.RuntimeException或java.lang.Error类衍生出来的。    * Checked exceptions:    定义方法时必须声明所有可能会抛出的checked exception;    在调用这个方法时,必须捕获它的checked exception,不然就得把它的exception传递下去;    checked exception是从java.lang.Exception类衍生出来的。    二、逻辑上    从逻辑的角度来说,checked exceptions和runtime exception是有不同的使用目的的。checked exception用来指示一种调用方能够直接处理的异常情况。而runtime exception则用来指示一种调用方本身无法处理或恢复的程序错误。    checked exception迫使你捕获它并处理这种异常情况。以java.net.URL类的构建器(constructor)为例,它的每一个构建器都会抛出MalformedURLException。MalformedURLException就是一种checked exception。设想一下,你有一个简单的程序,用来提示用户输入一个URL,然后通过这个URL去下载一个网页。如果用户输入的URL有错误,构建器就会抛出一个exception。既然这个exception是checked exception,你的程序就可以捕获它并正确处理:比如说提示用户重新输入。 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值