[算法] 中国农历算法

84 views
Skip to first unread message

kindy

unread,
Dec 26, 2007, 8:15:46 PM12/26/07
to Unitjs
转载,不记得出处了。

中国公历算法不是太难,关键是星期值的确定。这里给出了简单算法:

public static int dayOfWeek(int y, int m, int d) {
int w = 1; // 公历一年一月一日是星期一,所以起始值为星期日
y = (y-1)%400 + 1; // 公历星期值分部 400 年循环一次
int ly = (y-1)/4; // 闰年次数
ly = ly - (y-1)/100;
ly = ly + (y-1)/400;
int ry = y - 1 - ly; // 常年次数
w = w + ry; // 常年星期值增一
w = w + 2*ly; // 闰年星期值增二
w = w + dayOfYear(y,m,d);
w = (w-1)%7 + 1;
return w;
}

中国农历算法

根公历相比,中国农历的算法相当复杂。我在网上找的算法之中,eleworld.com 的算法是最好的一个。这个算法使用了大量的数据来确定农历月份
和节气的分部,它仅实用于公历 1901 年到 2100 年之间的 200 年。

中国农历计算程式

跟据 eleworld.com 提供的算法,我写了下面这个程式:

/**
* ChineseCalendarGB.java
* Copyright (c) 1997-2002 by Dr. Herong Yang
* 中国农历算法 - 实用于公历 1901 年至 2100 年之间的 200 年
*/
import java.text.*;
import java.util.*;
class ChineseCalendarGB {
private int gregorianYear;
private int gregorianMonth;
private int gregorianDate;
private boolean isGregorianLeap;
private int dayOfYear;
private int dayOfWeek; // 周日一星期的第一天
private int chineseYear;
private int chineseMonth; // 负数表示闰月
private int chineseDate;
private int sectionalTerm;
private int principleTerm;
private static char[] daysInGregorianMonth =
{31,28,31,30,31,30,31,31,30,31,30,31};
private static String[] stemNames =
{"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"};
private static String[] branchNames =
{"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};
private static String[] animalNames =
{"鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"};
public static void main(String[] arg) {
ChineseCalendarGB c = new ChineseCalendarGB();
String cmd = "day";
int y = 1901;
int m = 1;
int d = 1;
if (arg.length>0) cmd = arg[0];
if (arg.length>1) y = Integer.parseInt(arg[1]);
if (arg.length>2) m = Integer.parseInt(arg[2]);
if (arg.length>3) d = Integer.parseInt(arg[3]);
c.setGregorian(y,m,d);
c.computeChineseFields();
c.computeSolarTerms();
if (cmd.equalsIgnoreCase("year")) {
String[] t = c.getYearTable();
for (int i=0; i } else if (cmd.equalsIgnoreCase("month")) {
String[] t = c.getMonthTable();
for (int i=0; i } else {
System.out.println(c.toString());
}
}
public ChineseCalendarGB() {
setGregorian(1901,1,1);
}
public void setGregorian(int y, int m, int d) {
gregorianYear = y;
gregorianMonth = m;
gregorianDate = d;
isGregorianLeap = isGregorianLeapYear(y);
dayOfYear = dayOfYear(y,m,d);
dayOfWeek = dayOfWeek(y,m,d);
chineseYear = 0;
chineseMonth = 0;
chineseDate = 0;
sectionalTerm = 0;
principleTerm = 0;
}
public static boolean isGregorianLeapYear(int year) {
boolean isLeap = false;
if (year%4==0) isLeap = true;
if (year%100==0) isLeap = false;
if (year%400==0) isLeap = true;
return isLeap;
}
public static int daysInGregorianMonth(int y, int m) {
int d = daysInGregorianMonth[m-1];
if (m==2 && isGregorianLeapYear(y)) d++; // 公历闰年二月多一天
return d;
}
public static int dayOfYear(int y, int m, int d) {
int c = 0;
for (int i=1; i c = c + daysInGregorianMonth(y,i);
}
c = c + d;
return c;
}
public static int dayOfWeek(int y, int m, int d) {
int w = 1; // 公历一年一月一日是星期一,所以起始值为星期日
y = (y-1)%400 + 1; // 公历星期值分部 400 年循环一次
int ly = (y-1)/4; // 闰年次数
ly = ly - (y-1)/100;
ly = ly + (y-1)/400;
int ry = y - 1 - ly; // 常年次数
w = w + ry; // 常年星期值增一
w = w + 2*ly; // 闰年星期值增二
w = w + dayOfYear(y,m,d);
w = (w-1)%7 + 1;
return w;
}
private static char[] chineseMonths = {
// 农历月份大小压缩表,两个字节表示一年。两个字节共十六个二进制位数,
// 前四个位数表示闰月月份,后十二个位数表示十二个农历月份的大小。
0x00,0x04,0xad,0x08,0x5a,0x01,0xd5,0x54,0xb4,0x09,0x64,0x05,0x59,0x45,
0x95,0x0a,0xa6,0x04,0x55,0x24,0xad,0x08,0x5a,0x62,0xda,0x04,0xb4,0x05,
0xb4,0x55,0x52,0x0d,0x94,0x0a,0x4a,0x2a,0x56,0x02,0x6d,0x71,0x6d,0x01,
0xda,0x02,0xd2,0x52,0xa9,0x05,0x49,0x0d,0x2a,0x45,0x2b,0x09,0x56,0x01,
0xb5,0x20,0x6d,0x01,0x59,0x69,0xd4,0x0a,0xa8,0x05,0xa9,0x56,0xa5,0x04,
0x2b,0x09,0x9e,0x38,0xb6,0x08,0xec,0x74,0x6c,0x05,0xd4,0x0a,0xe4,0x6a,
0x52,0x05,0x95,0x0a,0x5a,0x42,0x5b,0x04,0xb6,0x04,0xb4,0x22,0x6a,0x05,
0x52,0x75,0xc9,0x0a,0x52,0x05,0x35,0x55,0x4d,0x0a,0x5a,0x02,0x5d,0x31,
0xb5,0x02,0x6a,0x8a,0x68,0x05,0xa9,0x0a,0x8a,0x6a,0x2a,0x05,0x2d,0x09,
0xaa,0x48,0x5a,0x01,0xb5,0x09,0xb0,0x39,0x64,0x05,0x25,0x75,0x95,0x0a,
0x96,0x04,0x4d,0x54,0xad,0x04,0xda,0x04,0xd4,0x44,0xb4,0x05,0x54,0x85,
0x52,0x0d,0x92,0x0a,0x56,0x6a,0x56,0x02,0x6d,0x02,0x6a,0x41,0xda,0x02,
0xb2,0xa1,0xa9,0x05,0x49,0x0d,0x0a,0x6d,0x2a,0x09,0x56,0x01,0xad,0x50,
0x6d,0x01,0xd9,0x02,0xd1,0x3a,0xa8,0x05,0x29,0x85,0xa5,0x0c,0x2a,0x09,
0x96,0x54,0xb6,0x08,0x6c,0x09,0x64,0x45,0xd4,0x0a,0xa4,0x05,0x51,0x25,
0x95,0x0a,0x2a,0x72,0x5b,0x04,0xb6,0x04,0xac,0x52,0x6a,0x05,0xd2,0x0a,
0xa2,0x4a,0x4a,0x05,0x55,0x94,0x2d,0x0a,0x5a,0x02,0x75,0x61,0xb5,0x02,
0x6a,0x03,0x61,0x45,0xa9,0x0a,0x4a,0x05,0x25,0x25,0x2d,0x09,0x9a,0x68,
0xda,0x08,0xb4,0x09,0xa8,0x59,0x54,0x03,0xa5,0x0a,0x91,0x3a,0x96,0x04,
0xad,0xb0,0xad,0x04,0xda,0x04,0xf4,0x62,0xb4,0x05,0x54,0x0b,0x44,0x5d,
0x52,0x0a,0x95,0x04,0x55,0x22,0x6d,0x02,0x5a,0x71,0xda,0x02,0xaa,0x05,
0xb2,0x55,0x49,0x0b,0x4a,0x0a,0x2d,0x39,0x36,0x01,0x6d,0x80,0x6d,0x01,
0xd9,0x02,0xe9,0x6a,0xa8,0x05,0x29,0x0b,0x9a,0x4c,0xaa,0x08,0xb6,0x08,
0xb4,0x38,0x6c,0x09,0x54,0x75,0xd4,0x0a,0xa4,0x05,0x45,0x55,0x95,0x0a,
0x9a,0x04,0x55,0x44,0xb5,0x04,0x6a,0x82,0x6a,0x05,0xd2,0x0a,0x92,0x6a,
0x4a,0x05,0x55,0x0a,0x2a,0x4a,0x5a,0x02,0xb5,0x02,0xb2,0x31,0x69,0x03,
0x31,0x73,0xa9,0x0a,0x4a,0x05,0x2d,0x55,0x2d,0x09,0x5a,0x01,0xd5,0x48,
0xb4,0x09,0x68,0x89,0x54,0x0b,0xa4,0x0a,0xa5,0x6a,0x95,0x04,0xad,0x08,
0x6a,0x44,0xda,0x04,0x74,0x05,0xb0,0x25,0x54,0x03
};
// 初始日,公历农历对应日期:
// 公历 1901 年 1 月 1 日,对应农历 4598 年 11 月 11 日
private static int baseYear = 1901;
private static int baseMonth = 1;
private static int baseDate = 1;
private static int baseIndex = 0;
private static int baseChineseYear = 4598-1;
private static int baseChineseMonth = 11;
private static int baseChineseDate = 11;
public int computeChineseFields() {
if (gregorianYear<1901 || gregorianYear>2100) return 1;
int startYear = baseYear;
int startMonth = baseMonth;
int startDate = baseDate;
chineseYear = baseChineseYear;
chineseMonth = baseChineseMonth;
chineseDate = baseChineseDate;
// 第二个对应日,用以提高计算效率
// 公历 2000 年 1 月 1 日,对应农历 4697 年 11 月 25 日
if (gregorianYear >= 2000) {
startYear = baseYear + 99;
startMonth = 1;
startDate = 1;
chineseYear = baseChineseYear + 99;
chineseMonth = 11;
chineseDate = 25;
}
int daysDiff = 0;
for (int i=startYear; i daysDiff += 365;
if (isGregorianLeapYear(i)) daysDiff += 1; // leap year
}
for (int i=startMonth; i daysDiff +=
daysInGregorianMonth(gregorianYear,i);
}
daysDiff += gregorianDate - startDate;

chineseDate += daysDiff;
int lastDate = daysInChineseMonth(chineseYear, chineseMonth);
int nextMonth = nextChineseMonth(chineseYear, chineseMonth);
while (chineseDate>lastDate) {
if (Math.abs(nextMonth) chineseMonth = nextMonth;
chineseDate -= lastDate;
lastDate = daysInChineseMonth(chineseYear, chineseMonth);
nextMonth = nextChineseMonth(chineseYear, chineseMonth);
}
return 0;
}
private static int[] bigLeapMonthYears = {
// 大闰月的闰年年份
6, 14, 19, 25, 33, 36, 38, 41, 44, 52,
55, 79,117,136,147,150,155,158,185,193
};
public static int daysInChineseMonth(int y, int m) {
// 注意:闰月 m < 0
int index = y - baseChineseYear + baseIndex;
int v = 0;
int l = 0;
int d = 30;
if (1<=m && m<=8) {
v = chineseMonths[2*index];
l = m - 1;
if ( ((v>>l)&0x01)==1 ) d = 29;
} else if (9<=m && m<=12) {
v = chineseMonths[2*index+1];
l = m - 9;
if ( ((v>>l)&0x01)==1 ) d = 29;
} else {
v = chineseMonths[2*index+1];
v = (v>>4)&0x0F;
if (v!=Math.abs(m)) {
d = 0;
} else {
d = 29;
for (int i=0; i if (bigLeapMonthYears[i]==index) {
d = 30;
break;
}
}
}
}
return d;
}
public static int nextChineseMonth(int y, int m) {
int n = Math.abs(m) + 1;
if (m>0) {
int index = y - baseChineseYear + baseIndex;
int v = chineseMonths[2*index+1];
v = (v>>4)&0x0F;
if (v==m) n = -m;
}
if (n==13) n = 1;
return n;
}
private static char[][] sectionalTermMap = {
{7,6,6,6,6,6,6,6,6,5,6,6,6,5,5,6,6,5,5,5,5,5,5,5,5,4,5,5},
{5,4,5,5,5,4,4,5,5,4,4,4,4,4,4,4,4,3,4,4,4,3,3,4,4,3,3,3},
{6,6,6,7,6,6,6,6,5,6,6,6,5,5,6,6,5,5,5,6,5,5,5,5,4,5,5,5,5},
{5,5,6,6,5,5,5,6,5,5,5,5,4,5,5,5,4,4,5,5,4,4,4,5,4,4,4,4,5},
{6,6,6,7,6,6,6,6,5,6,6,6,5,5,6,6,5,5,5,6,5,5,5,5,4,5,5,5,5},
{6,6,7,7,6,6,6,7,6,6,6,6,5,6,6,6,5,5,6,6,5,5,5,6,5,5,5,5,4,5,5,5,5},
{7,8,8,8,7,7,8,8,7,7,7,8,7,7,7,7,6,7,7,7,6,6,7,7,6,6,6,7,7},
{8,8,8,9,8,8,8,8,7,8,8,8,7,7,8,8,7,7,7,8,7,7,7,7,6,7,7,7,6,6,7,7,7},
{8,8,8,9,8,8,8,8,7,8,8,8,7,7,8,8,7,7,7,8,7,7,7,7,6,7,7,7,7},
{9,9,9,9,8,9,9,9,8,8,9,9,8,8,8,9,8,8,8,8,7,8,8,8,7,7,8,8,8},
{8,8,8,8,7,8,8,8,7,7,8,8,7,7,7,8,7,7,7,7,6,7,7,7,6,6,7,7,7},
{7,8,8,8,7,7,8,8,7,7,7,8,7,7,7,7,6,7,7,7,6,6,7,7,6,6,6,7,7}
};
private static char[][] sectionalTermYear = {
{13,49,85,117,149,185,201,250,250},
{13,45,81,117,149,185,201,250,250},
{13,48,84,112,148,184,200,201,250},
{13,45,76,108,140,172,200,201,250},
{13,44,72,104,132,168,200,201,250},
{5 ,33,68,96 ,124,152,188,200,201},
{29,57,85,120,148,176,200,201,250},
{13,48,76,104,132,168,196,200,201},
{25,60,88,120,148,184,200,201,250},
{16,44,76,108,144,172,200,201,250},
{28,60,92,124,160,192,200,201,250},
{17,53,85,124,156,188,200,201,250}
};
private static char[][] principleTermMap = {
{21,21,21,21,21,20,21,21,21,20,20,21,21,20,20,20,20,20,20,20,20,19,
20,20,20,19,19,20},
{20,19,19,20,20,19,19,19,19,19,19,19,19,18,19,19,19,18,18,19,19,18,
18,18,18,18,18,18},
{21,21,21,22,21,21,21,21,20,21,21,21,20,20,21,21,20,20,20,21,20,20,
20,20,19,20,20,20,20},
{20,21,21,21,20,20,21,21,20,20,20,21,20,20,20,20,19,20,20,20,19,19,
20,20,19,19,19,20,20},
{21,22,22,22,21,21,22,22,21,21,21,22,21,21,21,21,20,21,21,21,20,20,
21,21,20,20,20,21,21},
{22,22,22,22,21,22,22,22,21,21,22,22,21,21,21,22,21,21,21,21,20,21,
21,21,20,20,21,21,21},
{23,23,24,24,23,23,23,24,23,23,23,23,22,23,23,23,22,22,23,23,22,22,
22,23,22,22,22,22,23},
{23,24,24,24,23,23,24,24,23,23,23,24,23,23,23,23,22,23,23,23,22,22,
23,23,22,22,22,23,23},
{23,24,24,24,23,23,24,24,23,23,23,24,23,23,23,23,22,23,23,23,22,22,
23,23,22,22,22,23,23},
{24,24,24,24,23,24,24,24,23,23,24,24,23,23,23,24,23,23,23,23,22,23,
23,23,22,22,23,23,23},
{23,23,23,23,22,23,23,23,22,22,23,23,22,22,22,23,22,22,22,22,21,22,
22,22,21,21,22,22,22},
{22,22,23,23,22,22,22,23,22,22,22,22,21,22,22,22,21,21,22,22,21,21,
21,22,21,21,21,21,22}
};
private static char[][] principleTermYear = {
{13,45,81,113,149,185,201},
{21,57,93,125,161,193,201},
{21,56,88,120,152,188,200,201},
{21,49,81,116,144,176,200,201},
{17,49,77,112,140,168,200,201},
{28,60,88,116,148,180,200,201},
{25,53,84,112,144,172,200,201},
{29,57,89,120,148,180,200,201},
{17,45,73,108,140,168,200,201},
{28,60,92,124,160,192,200,201},
{16,44,80,112,148,180,200,201},
{17,53,88,120,156,188,200,201}
};
public int computeSolarTerms() {
if (gregorianYear<1901 || gregorianYear>2100) return 1;
sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);
principleTerm = principleTerm(gregorianYear, gregorianMonth);
return 0;
}
public static int sectionalTerm(int y, int m) {
if (y<1901 || y>2100) return 0;
int index = 0;
int ry = y-baseYear+1;
while (ry>=sectionalTermYear[m-1][index]) index++;
int term = sectionalTermMap[m-1][4*index+ry%4];
if ((ry == 121)&&(m == 4)) term = 5;
if ((ry == 132)&&(m == 4)) term = 5;
if ((ry == 194)&&(m == 6)) term = 6;
return term;
}
public static int principleTerm(int y, int m) {
if (y<1901 || y>2100) return 0;
int index = 0;
int ry = y-baseYear+1;
while (ry>=principleTermYear[m-1][index]) index++;
int term = principleTermMap[m-1][4*index+ry%4];
if ((ry == 171)&&(m == 3)) term = 21;
if ((ry == 181)&&(m == 5)) term = 21;
return term;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Gregorian Year: "+gregorianYear+"\n");
buf.append("Gregorian Month: "+gregorianMonth+"\n");
buf.append("Gregorian Date: "+gregorianDate+"\n");
buf.append("Is Leap Year: "+isGregorianLeap+"\n");
buf.append("Day of Year: "+dayOfYear+"\n");
buf.append("Day of Week: "+dayOfWeek+"\n");
buf.append("Chinese Year: "+chineseYear+"\n");
buf.append("Heavenly Stem: "+((chineseYear-1)%10)+"\n");
buf.append("Earthly Branch: "+((chineseYear-1)%12)+"\n");
buf.append("Chinese Month: "+chineseMonth+"\n");
buf.append("Chinese Date: "+chineseDate+"\n");
buf.append("Sectional Term: "+sectionalTerm+"\n");
buf.append("Principle Term: "+principleTerm+"\n");
return buf.toString();
}
public String[] getYearTable() {
setGregorian(gregorianYear,1,1);
computeChineseFields();
computeSolarTerms();
String[] table = new String[58]; // 6*9 + 4
table[0] = getTextLine(27, "公历年历:"+gregorianYear);
table[1] = getTextLine(27, "农历年历:"+(chineseYear+1)
+ " ("+stemNames[(chineseYear+1-1)%10]
+ branchNames[(chineseYear+1-1)%12]
+ " - "+animalNames[(chineseYear+1-1)%12]+"年)");
int ln = 2;
String blank = " "
+" " + " ";
String[] mLeft = null;
String[] mRight = null;
for (int i=1; i<=6; i++) {
table[ln] = blank;
ln++;
mLeft = getMonthTable();
mRight = getMonthTable();
for (int j=0; j String line = mLeft[j] + " " + mRight[j];
table[ln] = line;
ln++;
}
}
table[ln] = blank;
ln++;
table[ln] = getTextLine(0,
"##/## - 公历日期/农历日期,(*)#月 - (闰)农历月第一天");
ln++;
return table;
}
public static String getTextLine(int s, String t) {
String str = " "
+" " + " ";
if (t!=null && s str = str.substring(0,s) + t + str.substring(s
+t.length());
return str;
}
private static String[] monthNames =
{"一","二","三","四","五","六","七","八","九","十","十一","十二"};
public String[] getMonthTable() {
setGregorian(gregorianYear,gregorianMonth,1);
computeChineseFields();
computeSolarTerms();
String[] table = new String[8];
String title = null;
if (gregorianMonth<11) title = " ";
else title = " ";
title = title + monthNames[gregorianMonth-1] + "月"
+ " ";
String header = " 日 一 二 三 四 五 六 ";
String blank = " ";
table[0] = title;
table[1] = header;
int wk = 2;
String line = "";
for (int i=1; i line += " " + ' ';
}
int days = daysInGregorianMonth(gregorianYear,gregorianMonth);
for (int i=gregorianDate; i<=days; i++) {
line += getDateString() + ' ';
rollUpOneDay();
if (dayOfWeek==1) {
table[wk] = line;
line = "";
wk++;
}
}
for (int i=dayOfWeek; i<=7; i++) {
line += " " + ' ';
}
table[wk] = line;
for (int i=wk+1; i table[i] = blank;
}
for (int i=0; i table[i] = table[i].substring(0,table[i].length()-1);
}

return table;
}
private static String[] chineseMonthNames =
{"正","二","三","四","五","六","七","八","九","十","冬","腊"};
private static String[] principleTermNames =
{"大寒","雨水","春分","谷雨","夏满","夏至","大暑","处暑","秋分","霜降",
"小雪","冬至"};
private static String[] sectionalTermNames =
{"小寒","立春","惊蛰","清明","立夏","芒种","小暑","立秋","白露","寒露",
"立冬","大雪"};
public String getDateString() {
String str = "* / ";
String gm = String.valueOf(gregorianMonth);
if (gm.length()==1) gm = ' ' + gm;
String cm = String.valueOf(Math.abs(chineseMonth));
if (cm.length()==1) cm = ' ' + cm;
String gd = String.valueOf(gregorianDate);
if (gd.length()==1) gd = ' ' + gd;
String cd = String.valueOf(chineseDate);
if (cd.length()==1) cd = ' ' + cd;
if (gregorianDate==sectionalTerm) {
str = " "+sectionalTermNames[gregorianMonth-1];
} else if (gregorianDate==principleTerm) {
str = " "+principleTermNames[gregorianMonth-1];
} else if (chineseDate==1 && chineseMonth>0) {
str = " "+chineseMonthNames[chineseMonth-1]+"月";
} else if (chineseDate==1 && chineseMonth<0) {
str = "*"+chineseMonthNames[-chineseMonth-1]+"月";
} else {
str = gd+'/'+cd;
}
return str;
}
public int rollUpOneDay() {
dayOfWeek = dayOfWeek%7 + 1;
dayOfYear++;
gregorianDate++;
int days = daysInGregorianMonth(gregorianYear,gregorianMonth);
if (gregorianDate>days) {
gregorianDate = 1;
gregorianMonth++;
if (gregorianMonth>12) {
gregorianMonth = 1;
gregorianYear++;
dayOfYear = 1;
isGregorianLeap = isGregorianLeapYear(gregorianYear);
}
sectionalTerm = sectionalTerm(gregorianYear,gregorianMonth);
principleTerm = principleTerm(gregorianYear,gregorianMonth);
}
chineseDate++;
days = daysInChineseMonth(chineseYear,chineseMonth);
if (chineseDate>days) {
chineseDate = 1;
chineseMonth = nextChineseMonth(chineseYear,chineseMonth);
if (chineseMonth==1) chineseYear++;
}
return 0;
}
}

中国二百年年历 1901 年至 2100 年

我用上面这个程式制作了二百年年历,1901 年至 2100 年,全部收录在这本书中。

年历格式说明:

农历日期列在公历日期后面。
节气用节气名称标明。
农历每月第一天用月份名称标明。
例如,2000 年一月的表达格式如下:

一月
日 一 二 三 四 五 六
1/25
2/26 3/27 4/28 5/29 小寒 腊月 8/ 2
9/ 3 10/ 4 11/ 5 12/ 6 13/ 7 14/ 8 15/ 9
16/10 17/11 18/12 19/13 20/14 大寒 22/16
23/17 24/18 25/19 26/20 27/21 28/22 29/23
30/24 31/25

其中:

"1/25" - 表示公历 1 号和农历 25 号。
"小寒" - 表示节气。
"腊月" - 表示农历 12 月第一天。

kindy

unread,
Dec 26, 2007, 8:23:37 PM12/26/07
to Unitjs
还有一个


/
*****************************************************************************
日期资料
*****************************************************************************/

var lunarInfo=new Array(
0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,
0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0)

var solarMonth=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var Gan=new Array("甲","乙","丙","丁","戊","己","庚","辛","壬","癸");
var Zhi=new Array("子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥");
var Animals=new
Array("鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪");
var solarTerm = new Array("小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立
夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大
雪","冬至")
var sTermInfo = new
Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758)
var nStr1 = new Array('一','二','三','四','五','六','七','八','九','十')
var nStr2 = new Array('初','十','廿','卅',' ')
var monthName = new Array("1 月","2 月","3 月","4 月","5 月","6 月","7 月","8
月","9 月","10 月","11 月","12 月");

//国历节日 *表示放假日
var sFtv = new Array(
"0101*元旦",
"0214 情人节",
"0308 妇女节",
"0312 植树节",
"0315 消费者权益日",
"0401 愚人节",
"0501 劳动节",
"0504 青年节",
"0512 护士节",
"0601 儿童节",
"0701 建党节",
"0801 建军节",
"0808 父亲节",
"0909 毛泽东逝世纪念",
"0910 教师节",
"0928 孔子诞辰",
"1001*国庆节",
"1006 老人节",
"1024 联合国日",
"1112 孙中山诞辰",
"1220 澳门回归",
"1225 圣诞节",
"1226 毛泽东诞辰")

//农历节日 *表示放假日
var lFtv = new Array(
"0101*农历春节",
"0115 元宵节",
"0505 端午节",
"0707 七夕情人节",
"0815 中秋节",
"0909 重阳节",
"1208 腊八节",
"1224 小年",
"0100*除夕")

//某月的第几个星期几
var wFtv = new Array(
"0520 母亲节")

/
*****************************************************************************
日期计算
*****************************************************************************/

//====================================== 传回农历 y年的总天数
function lYearDays(y) {
var i, sum = 348
for(i=0x8000; i>0x8; i>>=1) sum += (lunarInfo[y-1900] & i)? 1: 0
return(sum+leapDays(y))
}

//====================================== 传回农历 y年闰月的天数
function leapDays(y) {
if(leapMonth(y)) return((lunarInfo[y-1900] & 0x10000)? 30: 29)
else return(0)
}

//====================================== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
function leapMonth(y) {
return(lunarInfo[y-1900] & 0xf)
}

//====================================== 传回农历 y年m月的总天数
function monthDays(y,m) {
return( (lunarInfo[y-1900] & (0x10000>>m))? 30: 29 )
}

//====================================== 算出农历, 传入日期物件, 传回农历日期物件
// 该物件属性
有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
function Lunar(objDate) {

var i, leap=0, temp=0
var baseDate = new Date(1900,0,31)
var offset = (objDate - baseDate)/86400000

this.dayCyl = offset + 40
this.monCyl = 14

for(i=1900; i<2050 && offset>0; i++) {
temp = lYearDays(i)
offset -= temp
this.monCyl += 12
}

if(offset<0) {
offset += temp;
i--;
this.monCyl -= 12
}

this.year = i
this.yearCyl = i-1864

leap = leapMonth(i) //闰哪个月
this.isLeap = false

for(i=1; i<13 && offset>0; i++) {
//闰月
if(leap>0 && i==(leap+1) && this.isLeap==false)
{ --i; this.isLeap = true; temp = leapDays(this.year); }
else
{ temp = monthDays(this.year, i); }

//解除闰月
if(this.isLeap==true && i==(leap+1)) this.isLeap = false

offset -= temp
if(this.isLeap == false) this.monCyl ++
}

if(offset==0 && leap>0 && i==leap+1)
if(this.isLeap)
{ this.isLeap = false; }
else
{ this.isLeap = true; --i; --this.monCyl;}

if(offset<0){ offset += temp; --i; --this.monCyl; }

this.month = i
this.day = offset + 1
}
/////////////////////////////////////////////////////////

var bsYear;
var bsDate;
var bsWeek;
var arrLen=8; //数组长度
var sValue=0; //当年的秒数
var dayiy=0; //当年第几天
var miy=0; //月份的下标
var iyear=0; //年份标记
var dayim=0; //当月第几天
var spd=86400; //每天的秒数

var year1999="30;29;29;30;29;29;30;29;30;30;30;29"; //354
var year2000="30;30;29;29;30;29;29;30;29;30;30;29"; //354
var year2001="30;30;29;30;29;30;29;29;30;29;30;29;30"; //384
var year2002="30;30;29;30;29;30;29;29;30;29;30;29"; //354
var year2003="30;30;29;30;30;29;30;29;29;30;29;30"; //355
var year2004="29;30;29;30;30;29;30;29;30;29;30;29;30"; //384
var year2005="29;30;29;30;29;30;30;29;30;29;30;29"; //354
var year2006="30;29;30;29;30;30;29;29;30;30;29;29;30";

var month1999="正月;二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月"
var month2001="正月;二月;三月;四月;闰四月;五月;六月;七月;八月;九月;十月;十一月;十二月"
var month2004="正月;二月;闰二月;三月;四月;五月;六月;七月;八月;九月;十月;十一月;十二月"
var month2006="正月;二月;三月;四月;五月;六月;七月;闰七月;八月;九月;十月;十一月;十二月"
var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;
廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十";

var Ys=new Array(arrLen);
Ys[0]=919094400;Ys[1]=949680000;Ys[2]=980265600;
Ys[3]=1013443200;Ys[4]=1044028800;Ys[5]=1074700800;
Ys[6]=1107878400;Ys[7]=1138464000;

var Yn=new Array(arrLen); //农历年的名称
Yn[0]="己卯年";Yn[1]="庚辰年";Yn[2]="辛巳年";
Yn[3]="壬午年";Yn[4]="癸未年";Yn[5]="甲申年";
Yn[6]="乙酉年";Yn[7]="丙戌年";
var D=new Date();
var yy=D.getYear();
var mm=D.getMonth()+1;
var dd=D.getDate();
var ww=D.getDay();
if (ww==0) ww="<font color=RED>星期日";
if (ww==1) ww="星期一";
if (ww==2) ww="星期二";
if (ww==3) ww="星期三";
if (ww==4) ww="星期四";
if (ww==5) ww="星期五";
if (ww==6) ww="<font color=RED>星期六";
ww=ww;
var ss=parseInt(D.getTime() / 1000);
if (yy<100) yy="19"+yy;

for (i=0;i<arrLen;i++)
if (ss>=Ys[i]){
iyear=i;
sValue=ss-Ys[i]; //当年的秒数
}
dayiy=parseInt(sValue/spd)+1; //当年的天数

var dpm=year1999;
if (iyear==1) dpm=year2000;
if (iyear==2) dpm=year2001;
if (iyear==3) dpm=year2002;
if (iyear==4) dpm=year2003;
if (iyear==5) dpm=year2004;
if (iyear==6) dpm=year2005;
if (iyear==7) dpm=year2006;
dpm=dpm.split(";");

var Mn=month1999;
if (iyear==2) Mn=month2001;
if (iyear==5) Mn=month2004;
if (iyear==7) Mn=month2006;
Mn=Mn.split(";");

var Dn="初一;初二;初三;初四;初五;初六;初七;初八;初九;初十;十一;十二;十三;十四;十五;十六;十七;十八;十九;二十;廿一;
廿二;廿三;廿四;廿五;廿六;廿七;廿八;廿九;三十";
Dn=Dn.split(";");

dayim=dayiy;

var total=new Array(13);
total[0]=parseInt(dpm[0]);
for (i=1;i<dpm.length-1;i++) total[i]=parseInt(dpm[i])+total[i-1];
for (i=dpm.length-1;i>0;i--)
if (dayim>total[i-1]){
dayim=dayim-total[i-1];
miy=i;
}
bsWeek=ww;
bsDate=yy+"年"+mm+"月";
bsDate2=dd;
bsYear="农历"+Yn[iyear];
bsYear2=Mn[miy]+Dn[dayim-1];
if (ss>=Ys[7]||ss<Ys[0]) bsYear=Yn[7];

function CAL(){
document.write("<table border='1' cellspacing='3' width='100'
bordercolor='#009B00' bgcolor='#FFFFFF' height='110'
cellpadding='2'");
document.write("<tr><td align='center'><b><font color=#008040>"+bsDate
+"</font><br><font face='Arial' size='6' color=#FF8040>"+bsDate2+"</
font><br><font color=#008040><span style='FONT-SIZE: 9pt'>");
document.write(bsWeek+"</span><br>"+"<br></b><font color=#9B4E00>");
document.write(bsYear+"<br>"+bsYear2+"</td></tr></table>");
}
function CAL2(){
document.write("<b>今天是:<font color=#008040>"+bsDate+bsDate2+"日</
font><font color=#008040>&nbsp;&nbsp;&nbsp;<span style='FONT-SIZE:
9pt'>");
document.write(bsWeek+"</span></b><font color=#9B4E00>");
document.write("&nbsp;&nbsp;&nbsp;<b>"+bsYear+bsYear2+"</b>");
}
Reply all
Reply to author
Forward
0 new messages