📄 calendar.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 + -