⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calendar.java

📁 本程序用Java描述了一个带有农历的万年历功能
💻 JAVA
字号:

//1981.3.1-2030.12.31
import java.io.*;
import javax.swing.JOptionPane;
import java.util.Scanner;

class LunarYear
{
	boolean[] monthDay = new boolean[12];
	byte lunarMonthPos = -1;
}

class SolarYear
{
	byte[] firstSTPos = new byte[12];          //ST = SolarTerms
	byte[] secondSTPos = new byte[12];         //
}

class ZhDate                               //Chinese Calendar  
{
	final static LunarYear[] ly = new LunarYear[40];
	final static SolarYear[] sy = new SolarYear[40];
	final static int[] DAY_MONTH = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};      //公历平年每月天数
	final static int[] DAY_RUN = {29, 29, 29, 29, 29, 29, 29, 29, 29,
								29, 29, 29, 29, 30, 29};
	final static String[] DAY = {"初一", "初二", "初三", "初四", "初五", 
						    	"初六", "初七", "初八", "初九", "初十",
						    	"十一", "十二", "十三", "十四", "十五",
						    	"十六", "十七", "十八", "十九", "二十",
						    	"廿一", "廿二", "廿三", "廿四", "廿五",
						    	"廿六", "廿七", "廿八", "廿九", "三十"};
	final static String[] MONTH = {"正月", "二月", "三月", "四月", "五月", "六月",
		                         "七月", "八月", "九月", "十月", "冬月", "腊月"};
	final static String[] SOLAR_TERMS = {"小寒", "大寒", "立春", "雨水", "惊蛰", "春分",
	    	                         "清明", "谷雨", "立夏", "小满", "芒种", "夏至",
	    	                         "小暑", "大暑", "立秋", "处暑", "白露", "秋分",
	    	                         "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};
	final static String[] ZODIAC = {"鼠", "牛", "虎", "兔", "龙", "蛇",
			                     "马", "羊", "猴", "鸡", "狗", "猪"};
	final static String[] HE_LOOP = {"甲子", "乙丑", "丙寅", "丁卯", "戊辰", "己巳",
								    	"庚午", "辛未", "壬申", "癸酉", "甲戌", "乙亥",
								    	"丙子", "丁丑", "戊寅", "己卯", "庚辰", "辛巳",
								    	"壬午", "癸未", "甲申", "乙酉", "丙戌", "丁亥",
								    	"戊子", "己丑", "庚寅", "辛卯", "壬辰", "癸巳",
								    	"甲午", "乙未", "丙申", "丁酉", "戊戌", "己亥",
								    	"庚子", "辛丑", "壬寅", "癸卯", "甲辰", "乙巳",
								    	"丙午", "丁未", "戊申", "己酉", "庚戌", "辛亥",
								    	"壬子", "癸丑", "甲寅", "乙卯", "丙辰", "丁巳",
								    	"戊午", "己未", "庚申", "辛酉", "壬戌", "癸亥",};
	int year;
	int month;
	int day;
	boolean isValid(int y, int m)
	{
		if (y<1981 || y>2020 || m<1 || m>12 || (y==1981 && (m<3||m>12)))
		    return false;
		return true; 
	}
	ZhDate(int year, int month) throws IOException            //initialization
	{
		this.year = year;
		this.month = month;
		this.day = 1;
		
		FileReader fr = new FileReader("data.dat");
		char[] buf = new char[15];
		//读入农历大小月信息
		for (int i=0; i<ly.length; ++i)
		{
			fr.read(buf);
			ly[i] = new LunarYear();
			switch (buf[0])
			{
				case 'f': ly[i].lunarMonthPos = -2;  break;
				default:  ly[i].lunarMonthPos = (byte)(buf[0]-'0');
			}
			for (int j=0; j<ly[i].monthDay.length; ++j)
			{
				if(buf[j+1]=='0')
				    ly[i].monthDay[j] = false;
				else
				    ly[i].monthDay[j] = true;
			}
		}
		fr.close();
		//读入节气信息
		fr = new FileReader("solarTerms.dat");
		char[] buffer = new char[14];
		for (int i=0; i<sy.length; ++i)
		{
			sy[i] = new SolarYear();
			fr.read(buffer);
			for (int j=0; j<sy[i].firstSTPos.length; ++j)
			{   //off = 3
				sy[i].firstSTPos[j] = (byte)(buffer[j]-'0');
			}
			fr.read(buffer);
			for (int j=0; j<sy[i].secondSTPos.length; ++j)
			{   //off = 17
				sy[i].secondSTPos[j] = (byte)(buffer[j]-'0');
			}
		}
	}
	boolean reset(int y, int m)
	{
		if (isValid(y, m))
		{
			year = y;
			month = m;
			return true;
		}
		return false;
	}
	void print()
	{
		for (int i=0; i<ly.length; ++i)
		{
			System.out.print(""+ly[i].lunarMonthPos);
			for (int j=0; j<ly[i].monthDay.length; ++j)
			{
				int k = 0;
				if (ly[i].monthDay[j])
				   k = 1;
				System.out.print(""+k);
			}
			System.out.println("");
		}
		for (int i=0; i<sy.length; ++i)
		{
			for (int j=0; j<sy[i].firstSTPos.length; ++j)
			    System.out.print(sy[i].firstSTPos[j]+"");
			System.out.println("");
			for (int j=0; j<sy[i].secondSTPos.length; ++j)
			    System.out.print(sy[i].secondSTPos[j]+"");
			System.out.println("");
		}
	}
	void printHead()
	{
		int y = (year-1864)%60;
		int zodiac = (year-1912)%12;
		System.out.println("公历:"+year+"年"+month+"月"+"		农历:"+HE_LOOP[y]+ZODIAC[zodiac]+"年"+"    m:月 d:日");
		System.out.println("日(Sun)    一(Mon)    二(Tue)    三(Wed)    四(Thu)    五(Fri)    六(Sat)");
		System.out.println("-------------------------------------------------------------------------");
	}
	int isST(int y, int m, int d)
	{
		y -= 1981;
		m--;
		if (sy[y].firstSTPos[m]==(d-3))
		    return (m*2);
		else if (sy[y].secondSTPos[m]==(d-17))
		    return (m*2+1);
		else return -1;
	}
	void printBody()
	{
		int flag = (getADay()+3)%7;                           //当月第一天位置
		int begPos = flag;
		int lFlag = flag;                                     //农历日期位置
		int jFlag = flag;                                     //纪年位置
		int addition = 0;
		if (month==2 && (year%4==0 && year%100!=0 || year%400==0))
		    addition = 1;
		
		//当月第一天农历月日
		int posY = 0;
		int posM = 0;
		int totalM = 0;
		int aDay = getADay()-35;
		int numMeetRun = -1;                                  //遇到闰月的次数 - 1
		boolean isRun = false;
loop:
		for (; ;)
		{
			//System.out.println(posY+" "+posM+" "+aDay);//
			isRun = false;
			int besides = 0;
			if (ly[posY].monthDay[posM])
			    besides = 1;
			if (aDay-29-besides<0)
				break loop;
			else
			{
				aDay -= (29+besides);
				if (ly[posY].lunarMonthPos==posM)                 
				{                          //闰月
					numMeetRun++;
					isRun = true;
					if (aDay-DAY_RUN[numMeetRun]<0)
					    break;
					else
						aDay -= DAY_RUN[numMeetRun];
				}
				posM++;
				totalM++;
				if (posM==12)
				{
					posM = 0;
					posY++;
				}
			}
		}                        //得到posM-aDay
		aDay--;                  //修正为数组下标
		
		//纪年
		int speY = posY;
		int speM = (totalM + 26)%60-1;
		if (speM==-1)
		    speM = 59;
		int speD = ((getADay()-35)%60 + 50)%60-1;
		if (speD==-1)
		    speD = 59;
		
		for (int i=0; i<flag; ++i)
		    System.out.print("           ");
		for (int i=0; i<DAY_MONTH[month-1]+addition; ++i)
		{
			//基本公历日期以及节气
			System.out.print(""+(i+1));
			int st = isST(year, month, i+1);
			if (-1!=st)
			    System.out.print("("+SOLAR_TERMS[st]+")   ");
			else
			    System.out.print("         ");
			if (i<9)
			    System.out.print(" ");
			
			flag++;
			if (flag%7==0 || i==(DAY_MONTH[month-1]+addition-1))
			{
				
			    System.out.println("");
			    //农历月日 lunar
			    if (lFlag<7)
				    for (int j=0; j<lFlag; ++j)
			    		System.out.print("           ");
			    do
			    {
			    	if (ly[posY].lunarMonthPos==posM && isRun)
			    	    System.out.print("闰");
			    	System.out.print(MONTH[posM]+DAY[aDay]+" ");
			    	if (!(ly[posY].lunarMonthPos==posM&&isRun))
			    	    System.out.print("  ");
			    	aDay++;
			    	int day = 29;
			    	if (isRun)
			    	{
			    		day = DAY_RUN[numMeetRun];
			    	}
			    	else
			    	{
			    		if (ly[posY].monthDay[posM])
			    		    day++;
			    	}
			    	if (day<=aDay)
			    	{
			    		aDay = 0;
			    		//如果下一个月是闰月,不能增加
			    		if (ly[posY].lunarMonthPos==posM && !isRun)
			    			isRun = true;
			    		else
			    		{
			    			posM++;
			    			isRun = false;
			    		}
			    	}
			    	if (posM==12)
			    	{
			    		posY++;
			    		posM = 0;
			    	}
			    	lFlag++;
			    	if (lFlag%7==0 && flag!=(DAY_MONTH[month-1]+addition+begPos))
			    	    System.out.println("");
		    	}while(lFlag%7!=0 && lFlag!=flag);
		    	if (flag==(DAY_MONTH[month-1]+addition+begPos))
		    	    System.out.println("");
		    	
		    	//纪年输出
		    	if (jFlag<7)
				    for (int j=0; j<jFlag; ++j)
			    		System.out.print("           ");
			    do
			    {
			    	System.out.print(HE_LOOP[speM]+"m"+HE_LOOP[speD]+"d ");
			    	speD++;
			    	int sst = isST(year, month, jFlag+i-flag+3);
			    	if (sst!=-1 && sst%2==0)
			    	    speM++;
			    	if (60==speD)
			    		speD = 0;
			    	if (speM==60)
			    	    speM = 0;
			    	jFlag++;
			    	if (jFlag%7==0)
			    	    System.out.println("");
			    }while(jFlag%7!=0 && jFlag!=flag);
		    	System.out.println("");
			}
		}
	}
	int getADay()
	{
		int aday = 0;
		for (int i=1981; i<year; ++i)
			if (i%4==0 && i%100!=0 || i%400==0)
			    aday += 366;
			else
			    aday += 365;
		for (int i=1; i<month; ++i)
		    aday += DAY_MONTH[i-1];
		aday += day;
		if ((year%4==0 && year%100!=0 || year%400==0) && month>=3)
		    aday++;
		return aday;
	}
	void run()
	{
		String y;
		String m;
	  int year = 2000;
	  int month = 1;
	  int command = 0;
		Scanner scan = new Scanner(System.in);
		do
		{
			if (command==0)
			{
				  y = JOptionPane.showInputDialog("year: (1981-2020)", "");
			    m = JOptionPane.showInputDialog("month:(1-12)\nspecial, in 1981, (3-12)", "");
			    try
			    {
			        year = Integer.parseInt(y);
			        month = Integer.parseInt(m);
		        }
		        catch(Exception e)
		        {
		        	year = 0;
		        	month = 0;
		        }
	    }
	        
			if (!this.reset(year, month))
			{
			    JOptionPane.showMessageDialog(null, "illegal data: "+year+"-"+month+"\nplease reinput", "Input error!", 1);    
			    command = 0;
			}
			else
			{
				this.printHead();
				this.printBody();
				do
				{
					System.out.println("0:Reinput  1:nextMonth  2:nextYear  3:preMonth  4:preYear  5:Quit");
					command = scan.nextInt();
					switch(command)
					{
						case 0:  command = 0;  break;
						case 1:  command = 1;  month++;  break;
						case 2:  command = 1;  year++;   break;
						case 3:  command = 1;  month--;  break;
						case 4:  command = 1;  year--;   break;
						case 5:  command = 5;  break;
						default: JOptionPane.showMessageDialog(null, "boring command...", "error", 1); command = 6;
					}
				}while(command==6);
			}
		}while(command!=5);
	}
	public static void main(String[] args)
	{
		try
		{
			ZhDate zd = new ZhDate(2000, 1);
			zd.run();
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null, "fail to read file \"data.dat\" or \"solarTerms\"", "IO Error", 1);
		}
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -