0
点赞
收藏
分享

微信扫一扫

中国农历算法java实现

中国农历算法java实现_sed

n 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<gregorianYear; i++) {

          daysDiff += 365;

          if (isGregorianLeapYear(i)) daysDiff += 1; // leap year

       }

       for (int i=startMonth; i<gregorianMonth; 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)<Math.abs(chineseMonth)) chineseYear++;

          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<bigLeapMonthYears.length; 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<mLeft.length; 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.length() && s+t.length()<str.length())

          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<dayOfWeek; 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.length; i++) {

          table[i] = blank;

       }

       for (int i=0; i<table.length; 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 月第一天。
举报

相关推荐

0 条评论