Java编写多功能万年历程序的实例分享

这里的万年历制作主要用到了Calendar类和GregorianCalendar类,我们先来回顾一下基础知识:

基础部分

一、Calendar类。
1,主要字段:
YEAR(年份)、MONTH(月份从0开始)、DATE(一月的某天)、HOUR(指示上午或下午的小时)、HOUR_F_DAY(指示一天中的小时。)、DAY_OF_WEEK (一个星期中的某天)、DAY_OF_MONTH(一个月中的某天)、DAY_OF_YEAR(一年中的某天)、DAY_OF_WEEK _IN_MONTH(一个月中的第几个星期)、WEEK_OF_MONTH  (指示当前月中的星期数)、WEEK_OF_YEAR(指示当前年中的星期数)
2,得Calendar类对象。

//通过 Calendar类的静态方法getInstance获得。
Calendar ca = Calendar.getInstance();

3,主要方法

void set(int field,int value)//field日历类的参数,比如YEAR MONTH DATE 等...
void set(int year,int month,int date)//设置年月日。
void set(int year, int month, int date, int hourOfDay, int minute)//设置年月日时分
void set(int year, int month, int date, int hourOfDay, int minute, int second)//设置年月日时分秒
void setTime(Date date);//使用给定的 Date 设置此 Calendar 的时间。

int get(int field)//返回给定日历字段的值。如:int month = acobj.get(Calendar.MONTH);
Date getTime()//返回一个表示此 Calendar 时间值的 Date 对象。
long getTimeInMillis()//返回从1970.1.1 00:00:00到该日历的毫秒数。

void add(int field,amont);//根据日历的规则,为给定的日历字段添加或减去指定的时间量。可加减。如:caobj.add(Calendar.MONTH,1)下一个月。

二、GregorianCalendar类。
1,获得该类对象

Calendar ca = new GregorianCalendar()//默认当前的时刻。
Calendar ca = new GregorianCanlendar(int year,int month,int dayOfMonth)//初始具有指定年月日的公历类对象。
Calendar ca = new GregorianCanlendar(int year,int month,int dayOfMonth,int hourOfDay,int minute)初始具有指定年月日的公历类对象。
Calendar ca = new GregorianCanlendar(int year,int month,int dayOfMonth,int hourOfDay,int minute,int second)//初始具有指定年月日的公历类对象。
上边的都是获得默认的语言环境,和默认的时区 对象。

2,用法
用法主要继承去父类Calendar。

实例部分
三、万年历代码

package com.via.mce.monthcalendar.utils;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;

/**
 * 农历日历。<br>
 * 将农历从1901年到2100年之间各年、月的大小以及历年节气保存,然后基于这些数据进行计算。<br>
 * <br>
 * 新增了几个用于农历的常量属性字段,可以使用get()方法获取日历对应的值;<br>
 * 农历年、月、日还可以使用set()/add()/roll()方法设置,其他农历属性自动计算;<br>
 * 另外,还提供了getChinese(int field)方法用于获得农历的中文文字(仅适用于农历属性和星期)。<br>
 * <ul>
 * <li>CHINESE_YEAR - 农历年</li>
 * <li>CHINESE_MONTH - 农历月</li>
 * <li>CHINESE_DATE - 农历日</li>
 * <li>CHINESE_SECTIONAL_TERM - 当月的节气</li>
 * <li>CHINESE_PRINCIPLE_TERM - 当月的中气</li>
 * <li>CHINESE_HEAVENLY_STEM - 农历年的天干</li>
 * <li>CHINESE_EARTHLY_BRANCH - 农历年的地支</li>
 * <li>CHINESE_ZODIAC - 农历年的属相</li>
 * <li>CHINESE_TERM_OR_DATE - 如果当天存在一个节气则指示节气,否则如果当天是初一则指示农历月,否则指示农历日</li>
 * </ul>
 * 注意:<br>
 * 由于Calendar类的设定,公历月份从0起始。所有方法都遵循了这一约定。<br>
 * 但所有的农历属性从1起始。即使是在Calendar提供的方法中,农历月也是从1起始的,并以负数表示闰月。<br>
 * clear()方法在某些情况下会导致农历和公历日期不对应或是不能达到预期的重置效果,应尽量避免使用。<br>
 * 使用getSimpleDateString()获得公历日期字符串时,公历月已经修正;<br>
 * 使用getSimpleChineseDateString()获得农历日期字符串时,农历闰月以*表示。<br>
 *
 * @version 0.12 2011-9-5 <br>
 *   <blockquote>修复一个当使用农历正月日期初始化日历时陷入死循环的问题。</blockquote>
 * @version 0.11 2009-12-27 <br>
 *   <blockquote>修复了获取中文农历时未计算农历日期的问题;<br>
 *   加入一个字段CHINESE_TERM_OR_DATE用于模仿台历的显示方式:如果当天有节气则指示节气,如果是初一指示农历月,
 *   否则指示农历日。</blockquote>
 * @version 0.10 2009-12-22
 */
public final class ChineseCalendar extends GregorianCalendar {
 private static final long serialVersionUID = 8L;

 /** 农历年 */
 public static final int CHINESE_YEAR = 801;
 /** 农历月 */
 public static final int CHINESE_MONTH = 802;
 /** 农历日 */
 public static final int CHINESE_DATE = 803;
 /** 当月的节气对应的公历日(前一个节气) */
 public static final int CHINESE_SECTIONAL_TERM = 804;
 /** 当月的中气对应的公历日(后一个节气) */
 public static final int CHINESE_PRINCIPLE_TERM = 805;
 /** 天干 */
 public static final int CHINESE_HEAVENLY_STEM = 806;
 /** 地支 */
 public static final int CHINESE_EARTHLY_BRANCH = 807;
 /** 农历年的属相(生肖) */
 public static final int CHINESE_ZODIAC = 808;
 /** 节气或者农历日 */
 public static final int CHINESE_TERM_OR_DATE = 888;

 // add by skywang
 /** 农历节日 */
 public static final int LUNAR_FESTIVAL = 809;
 /** 阳历节日 */
 public static final int SOLAR_FESTIVAL = 810;
 /** 节气 */
 public static final int CHINESE_TERM = 811;
 /** 月或者农历日 */
 public static final int CHINESE_MONTH_OR_DATE = 812;
 /** 节日 或 节气 或 农历日 */
 public static final int FESTIVAL_OR_TERM_OR_DATE = 813;

 private int chineseYear;
 private int chineseMonth; // 1起始,负数表示闰月
 private int chineseDate;
 private int sectionalTerm; // 当月节气的公历日
 private int principleTerm; // 当月中气的公历日

 private boolean areChineseFieldsComputed; // 农历日期是否已经经过计算确认
 private boolean areSolarTermsComputed; // 节气是否已经经过计算确认
 private boolean lastSetChinese; // 最后设置的是不是农历属性

 /** 使用当前时间构造一个实例。 */
 public ChineseCalendar() {
  super();
 }

 /** 使用指定时间构造一个实例。 */
 public ChineseCalendar(Date d) {
  super.setTime(d);
 }

 /** 使用指定时间构造一个实例。 */
 public ChineseCalendar(Calendar c) {
  this(c.getTime());
 }

 /** 使用指定公历日期构造一个实例。 */
 public ChineseCalendar(int y, int m, int d) {
  super(y, m, d);
 }

 /**
  * 使用指定日期构造一个实例。
  *
  * @param isChinese
  *   是否为农历日期
  * @param y
  * @param m
  * @param d
  */
 public ChineseCalendar(boolean isChinese, int y, int m, int d) {
  if (isChinese) {
   set(CHINESE_YEAR, y);
   set(CHINESE_MONTH, m);
   set(CHINESE_DATE, d);
  } else {
   set(y, m, d);
  }
 }

 public void set(int field, int value) {
  computeIfNeed(field);

  if (isChineseField(field)) {
   // 农历属性
   switch (field) {
   case CHINESE_YEAR:
    chineseYear = value;
    break;
   case CHINESE_MONTH:
    chineseMonth = value;
    break;
   case CHINESE_DATE:
    chineseDate = value;
    break;
   default:
    throw new IllegalArgumentException("不支持的field设置:" + field);
   }
   lastSetChinese = true;
  } else {
   // 非农历属性
   super.set(field, value);
   lastSetChinese = false;
  }
  areFieldsSet = false;
  areChineseFieldsComputed = false;
  areSolarTermsComputed = false;
 }

 public int get(int field) {
  computeIfNeed(field);

  if (!isChineseField(field)) {
   return super.get(field);
  }

  switch (field) {
  case CHINESE_YEAR:
   return chineseYear;
  case CHINESE_MONTH:
   return chineseMonth;
  case CHINESE_DATE:
   return chineseDate;
  case CHINESE_SECTIONAL_TERM:
   return sectionalTerm;
  case CHINESE_PRINCIPLE_TERM:
   return principleTerm;
  case CHINESE_HEAVENLY_STEM:
   return (chineseYear - 4) % 10 + 1;
  case CHINESE_EARTHLY_BRANCH:
  case CHINESE_ZODIAC:
   return (chineseYear - 4) % 12 + 1;
  case CHINESE_MONTH_OR_DATE:
   if (get(CHINESE_DATE) == 1) {
    return CHINESE_MONTH;
   } else {
    return CHINESE_DATE;
   }
  case CHINESE_TERM_OR_DATE:
   int option;
   if (get(Calendar.DATE) == get(CHINESE_SECTIONAL_TERM)) {
    option = CHINESE_SECTIONAL_TERM;
   } else if (get(Calendar.DATE) == get(CHINESE_PRINCIPLE_TERM)) {
    option = CHINESE_PRINCIPLE_TERM;
   } else if (get(CHINESE_DATE) == 1) {
    option = CHINESE_MONTH;
   } else {
    option = CHINESE_DATE;
   }
   return option;
  default:
   throw new IllegalArgumentException("不支持的field获取:" + field);
  }
 }

 public void add(int field, int amount) {
  computeIfNeed(field);

  if (!isChineseField(field)) {
   super.add(field, amount);
   lastSetChinese = false;
   areChineseFieldsComputed = false;
   areSolarTermsComputed = false;
   return;
  }

  switch (field) {
  case CHINESE_YEAR:
   chineseYear += amount;
   break;
  case CHINESE_MONTH:
   for (int i = 0; i < amount; i++) {
    chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
    if (chineseMonth == 1) {
     chineseYear++;
    }
   }
   break;
  case CHINESE_DATE:
   int maxDate = daysInChineseMonth(chineseYear, chineseMonth);
   for (int i = 0; i < amount; i++) {
    chineseDate++;
    if (chineseDate > maxDate) {
     chineseDate = 1;
     chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
     if (chineseMonth == 1) {
      chineseYear++;
     }
     maxDate = daysInChineseMonth(chineseYear, chineseMonth);
    }
   }
  default:
   throw new IllegalArgumentException("不支持的field:" + field);
  }

  lastSetChinese = true;
  areFieldsSet = false;
  areChineseFieldsComputed = false;
  areSolarTermsComputed = false;
 }

 public void roll(int field, int amount) {
  computeIfNeed(field);

  if (!isChineseField(field)) {
   super.roll(field, amount);
   lastSetChinese = false;
   areChineseFieldsComputed = false;
   areSolarTermsComputed = false;
   return;
  }

  switch (field) {
  case CHINESE_YEAR:
   chineseYear += amount;
   break;
  case CHINESE_MONTH:
   for (int i = 0; i < amount; i++) {
    chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
   }
   break;
  case CHINESE_DATE:
   int maxDate = daysInChineseMonth(chineseYear, chineseMonth);
   for (int i = 0; i < amount; i++) {
    chineseDate++;
    if (chineseDate > maxDate) {
     chineseDate = 1;
    }
   }
  default:
   throw new IllegalArgumentException("不支持的field:" + field);
  }

  lastSetChinese = true;
  areFieldsSet = false;
  areChineseFieldsComputed = false;
  areSolarTermsComputed = false;
 }

 /**
  * 获得属性的中文,可以使用的属性字段为DAY_OF_WEEK以及所有农历属性字段。
  *
  * @param field
  * @return
  */
 public String getChinese(int field) {
  computeIfNeed(field);

  switch (field) {
  case CHINESE_YEAR:
   return getChinese(CHINESE_HEAVENLY_STEM)
     + getChinese(CHINESE_EARTHLY_BRANCH) + "年";
  case CHINESE_MONTH:
   if (chineseMonth > 0)
    return chineseMonthNames[chineseMonth] + "月";
   else
    return "闰" + chineseMonthNames[-chineseMonth] + "月";
  case CHINESE_DATE:
   return chineseDateNames[chineseDate];
  case CHINESE_SECTIONAL_TERM:
   return sectionalTermNames[get(Calendar.MONTH)];
  case CHINESE_PRINCIPLE_TERM:
   return principleTermNames[get(Calendar.MONTH)];
  case CHINESE_HEAVENLY_STEM:
   return stemNames[get(field)];
  case CHINESE_EARTHLY_BRANCH:
   return branchNames[get(field)];
  case CHINESE_ZODIAC:
   return animalNames[get(field)];
  case Calendar.DAY_OF_WEEK:
   return chineseWeekNames[get(field)];
  case CHINESE_TERM_OR_DATE:
   return getChinese(get(CHINESE_TERM_OR_DATE));
  case LUNAR_FESTIVAL:
   return getLunarFestival();
  case SOLAR_FESTIVAL:
   return getSolarFestival();
  case FESTIVAL_OR_TERM_OR_DATE:
   return getFestivalOrTermOrDate();
   // TODO CHECK
  case CHINESE_MONTH_OR_DATE:
   return getChinese(get(CHINESE_MONTH_OR_DATE));
  case CHINESE_TERM:
   return getChineseTerm();
  default:
   throw new IllegalArgumentException("不支持的field中文获取:" + field);
  }
 }

 public String getSimpleGregorianDateString() {
  return new StringBuffer().append(get(YEAR)).append("-")
    .append(get(MONTH) + 1).append("-").append(get(DATE))
    .toString();
 }

 public String getSimpleChineseDateString() {
  return new StringBuffer()
    .append(get(CHINESE_YEAR))
    .append("-")
    .append(get(CHINESE_MONTH) > 0 ? "" + get(CHINESE_MONTH) : "*"
      + (-get(CHINESE_MONTH))).append("-")
    .append(get(CHINESE_DATE)).toString();
 }

 public String getChineseDateString() {
  return new StringBuffer().append(getChinese(CHINESE_YEAR))
    .append(getChinese(CHINESE_MONTH))
    .append(getChinese(CHINESE_DATE)).toString();
 }

 public String toString() {
  StringBuffer buf = new StringBuffer();
  buf.append(getSimpleGregorianDateString()).append(" | ")
    .append(getChinese(DAY_OF_WEEK)).append(" | [农历]")
    .append(getChineseDateString()).append(" ")
    .append(getChinese(CHINESE_ZODIAC)).append("年 ")
    .append(get(CHINESE_SECTIONAL_TERM)).append("日")
    .append(getChinese(CHINESE_SECTIONAL_TERM)).append(" ")
    .append(get(CHINESE_PRINCIPLE_TERM)).append("日")
    .append(getChinese(CHINESE_PRINCIPLE_TERM));
  return buf.toString();
 }

 /**
  * 判断是不是农历属性
  *
  * @param field
  * @return
  */
 private boolean isChineseField(int field) {
  switch (field) {
  case CHINESE_YEAR:
  case CHINESE_MONTH:
  case CHINESE_DATE:
  case CHINESE_SECTIONAL_TERM:
  case CHINESE_PRINCIPLE_TERM:
  case CHINESE_HEAVENLY_STEM:
  case CHINESE_EARTHLY_BRANCH:
  case CHINESE_ZODIAC:
  case CHINESE_TERM_OR_DATE:
  case CHINESE_MONTH_OR_DATE:
   return true;
  default:
   return false;
  }
 }

 /**
  * 判断是不是与节气有关的属性
  *
  * @param field
  * @return
  */
 private boolean isChineseTermsField(int field) {
  switch (field) {
  case CHINESE_SECTIONAL_TERM:
  case CHINESE_PRINCIPLE_TERM:
  case CHINESE_TERM_OR_DATE:
   return true;
  default:
   return false;
  }
 }

 /**
  * 如果上一次设置的与这次将要设置或获取的属性不是同一类(农历/公历),<br>
  * 例如上一次设置的是农历而现在要设置或获取公历,<br>
  * 则需要先根据之前设置的农历日期计算出公历日期。
  *
  * @param field
  */
 private void computeIfNeed(int field) {
  if (isChineseField(field)) {
   if (!lastSetChinese && !areChineseFieldsComputed) {
    super.complete();
    computeChineseFields();
    areFieldsSet = true;
    areChineseFieldsComputed = true;
    areSolarTermsComputed = false;
   }
   if (isChineseTermsField(field) && !areSolarTermsComputed) {
    computeSolarTerms();
    areSolarTermsComputed = true;
   }
  } else {
   if (lastSetChinese && !areFieldsSet) {
    computeGregorianFields();
    super.complete();
    areFieldsSet = true;
    areChineseFieldsComputed = true;
    areSolarTermsComputed = false;
   }
  }
 }

 /**
  * 使用农历日期计算出公历日期
  */
 private void computeGregorianFields() {
  int y = chineseYear;
  int m = chineseMonth;
  int d = chineseDate;
  areChineseFieldsComputed = true;
  areFieldsSet = true;
  lastSetChinese = false;

  // 调整日期范围
  if (y < 1900)
   y = 1899;
  else if (y > 2100)
   y = 2101;

  if (m < -12)
   m = -12;
  else if (m > 12)
   m = 12;

  if (d < 1)
   d = 1;
  else if (d > 30)
   d = 30;

  int dateint = y * 10000 + Math.abs(m) * 100 + d;
  if (dateint < 19001111) { // 太小
   set(1901, Calendar.JANUARY, 1);
   super.complete();
  } else if (dateint > 21001201) { // 太大
   set(2100, Calendar.DECEMBER, 31);
   super.complete();
  } else {
   if (Math.abs(m) > 12) {
    m = 12;
   }
   int days = ChineseCalendar.daysInChineseMonth(y, m);
   if (days == 0) {
    m = -m;
    days = ChineseCalendar.daysInChineseMonth(y, m);
   }
   if (d > days) {
    d = days;
   }
   set(y, Math.abs(m) - 1, d);
   computeChineseFields();

   int amount = 0;
   while (chineseYear != y || chineseMonth != m) {
    amount += daysInChineseMonth(chineseYear, chineseMonth);
    chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
    if (chineseMonth == 1) {
     chineseYear++;
    }
   }
   amount += d - chineseDate;

   super.add(Calendar.DATE, amount);
  }
  computeChineseFields();
 }

 /**
  * 使用公历日期计算出农历日期
  */
 private void computeChineseFields() {
  int gregorianYear = internalGet(Calendar.YEAR);
  int gregorianMonth = internalGet(Calendar.MONTH) + 1;
  int gregorianDate = internalGet(Calendar.DATE);

  if (gregorianYear < 1901 || gregorianYear > 2100) {
   return;
  }

  int startYear, startMonth, startDate;
  if (gregorianYear < 2000) {
   startYear = baseYear;
   startMonth = baseMonth;
   startDate = baseDate;
   chineseYear = baseChineseYear;
   chineseMonth = baseChineseMonth;
   chineseDate = baseChineseDate;
  } else {
   // 第二个对应日,用以提高计算效率
   // 公历 2000 年 1 月 1 日,对应农历 4697(1999) 年 11 月 25 日
   startYear = baseYear + 99;
   startMonth = 1;
   startDate = 1;
   chineseYear = baseChineseYear + 99;
   chineseMonth = 11;
   chineseDate = 25;
  }

  int daysDiff = 0;

  // 年
  for (int i = startYear; i < gregorianYear; i++) {
   if (isGregorianLeapYear(i)) {
    daysDiff += 366; // leap year
   } else {
    daysDiff += 365;
   }
  }

  // 月
  for (int i = startMonth; i < gregorianMonth; i++) {
   daysDiff += daysInGregorianMonth(gregorianYear, i - 1);
  }

  // 日
  daysDiff += gregorianDate - startDate;

  chineseDate += daysDiff;

  int lastDate = daysInChineseMonth(chineseYear, chineseMonth);
  while (chineseDate > lastDate) {
   chineseDate -= lastDate;
   chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
   if (chineseMonth == 1) {
    chineseYear++;
   }
   lastDate = daysInChineseMonth(chineseYear, chineseMonth);
  }

 }

 /**
  * 计算节气
  */
 private void computeSolarTerms() {
  int gregorianYear = internalGet(Calendar.YEAR);
  int gregorianMonth = internalGet(Calendar.MONTH);

  if (gregorianYear < 1901 || gregorianYear > 2100) {
   return;
  }
  sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);
  principleTerm = principleTerm(gregorianYear, gregorianMonth);
 }

 /* 接下来是静态方法~ */
 /**
  * 是否为公历闰年
  *
  * @param year
  * @return
  */
 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;
 }

 /**
  * 计算公历年的当月天数,公历月从0起始!
  *
  * @param y
  * @param m
  * @return
  */
 public static int daysInGregorianMonth(int y, int m) {
  int d = daysInGregorianMonth[m];
  if (m == Calendar.FEBRUARY && isGregorianLeapYear(y)) {
   d++; // 公历闰年二月多一天
  }
  return d;
 }

 /**
  * 计算公历年当月的节气,公历月从0起始!
  *
  * @param y
  * @param m
  * @return
  */
 public static int sectionalTerm(int y, int m) {
  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;
 }

 /**
  * 计算公历年当月的中气,公历月从0起始!
  *
  * @param y
  * @param m
  * @return
  */
 public static int principleTerm(int y, int m) {
  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;
 }

 /**
  * 计算农历年的天数
  *
  * @param y
  * @param m
  * @return
  */
 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;
 }

 /**
  * 计算农历的下个月
  *
  * @param y
  * @param m
  * @return
  */
 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 final int baseYear = 1901;
 private static final int baseMonth = 1;
 private static final int baseDate = 1;
 private static final int baseIndex = 0;
 private static final int baseChineseYear = 1900;
 private static final int baseChineseMonth = 11;
 private static final int baseChineseDate = 11;

 /* 中文字符串 */
 private static final String[] chineseWeekNames = { "", "星期日", "星期一", "星期二",
   "星期三", "星期四", "星期五", "星期六" };
 private static final String[] chineseMonthNames = { "", "正", "二", "三", "四",
   "五", "六", "七", "八", "九", "十", "十一", "十二" };
 private static final String[] chineseDateNames = { "", "初一", "初二", "初三",
   "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四",
   "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五",
   "廿六", "廿七", "廿八", "廿九", "三十" };
 private static final String[] principleTermNames = { "大寒", "雨水", "春分",
   "谷雨", "夏满", "夏至", "大暑", "处暑", "秋分", "霜降", "小雪", "冬至" };
 private static final String[] sectionalTermNames = { "小寒", "立春", "惊蛰",
   "清明", "立夏", "芒种", "小暑", "立秋", "白露", "寒露", "立冬", "大雪" };
 private static final String[] stemNames = { "", "甲", "乙", "丙", "丁", "戊",
   "己", "庚", "辛", "壬", "癸" };
 private static final String[] branchNames = { "", "子", "丑", "寅", "卯", "辰",
   "巳", "午", "未", "申", "酉", "戌", "亥" };
 private static final String[] animalNames = { "", "鼠", "牛", "虎", "兔", "龙",
   "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };

 /* 接下来是数据压缩表~ */
 private static final int[] bigLeapMonthYears = { 6, 14, 19, 25, 33, 36, 38,
   41, 44, 52, 55, 79, 117, 136, 147, 150, 155, 158, 185, 193 };
 private static final 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 final 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 final 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 final 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 } };

 private static final char[] daysInGregorianMonth = { 31, 28, 31, 30, 31,
   30, 31, 31, 30, 31, 30, 31 };
 private static final 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 };

 private String getChineseTerm() {
  if (get(Calendar.DATE) == get(CHINESE_SECTIONAL_TERM)) {
   return sectionalTermNames[get(Calendar.MONTH)];
  } else if (get(Calendar.DATE) == get(CHINESE_PRINCIPLE_TERM)) {
   return principleTermNames[get(Calendar.MONTH)];
  } else
   return null;
 }
 // add by skywang
 private String getLunarFestival() {
  int day = get(CHINESE_DATE);
  int month = get(CHINESE_MONTH);
  String sToday = day < 10 ? "0" + day:"" + day;
  String sMonth = month<10 ? "0" +(month):""+(month);

  return lFestival.get(sMonth+sToday);
 }
 private String getSolarFestival() {
  int day = get(Calendar.DATE);
  int month = get(Calendar.MONTH);
  String sToday = day < 10 ? "0" + day:"" + day;
  String sMonth = month<10 ? "0" +(month+1):""+(month+1);

  return sFestival.get(sMonth+sToday);
 }
 private String getFestivalOrTermOrDate() {
  String ret;
  if ((ret = getSolarFestival()) != null)
   return ret;
  if ((ret = getLunarFestival()) != null)
   return ret;
  return getChinese(get(CHINESE_TERM_OR_DATE));
 }

 //公历节日
 private static HashMap<String,String> sFestival =new HashMap<String,String>();
 // 农历介入
 private static HashMap<String,String> lFestival =new HashMap<String,String>();
 static {
  sFestival.put("0101","元旦");
  sFestival.put("0214","情人节");
  sFestival.put("0308","妇女节");
  sFestival.put("0312","植树节");
  sFestival.put("0401","愚人节");
  sFestival.put("0501","劳动节");
  sFestival.put("0504","青年节");
  sFestival.put("0601","儿童节");
  sFestival.put("0701","建党节");
  sFestival.put("0801","建军节");
  sFestival.put("0910","教师节");
  sFestival.put("1001","国庆节");
  sFestival.put("1031","万圣节");
//  sFestival.put("1112","孙中山诞辰");
  sFestival.put("1225","圣诞节");  

  lFestival.put("0101","春节");
//  lFestival.put("0102","大年初二");
//  lFestival.put("0103","大年初三");
  lFestival.put("0115","元宵节");
  lFestival.put("0505","端午节");
  lFestival.put("0707","七夕");
  lFestival.put("0815","中秋节");
  lFestival.put("0909","重阳节");
  lFestival.put("1208","腊八节");
//  lFestival.put("1299","除夕");
 }
}
(0)

相关推荐

  • java万年历,获取该年月日历表

    这篇文章应用java技术输入年份和月份获取该年月日历表,下面通过一段代码给大家做展示: 输入年份和月份,打印出这个月的日历表     1.1900年1月1日是星期一     2.计算输入的年份距离1900年有多少天再计算当年1月1日距这个月有多少天     3.总天数%7得出从星期几开始     注:计算机中的时间最小到1900年,此外UNIX系统认为1970年1月1日0点是时间纪元.     so,在本程序中不考了1900年以前的年份了.有兴趣的可以自己研究下. import java.uti

  • Java基础之打印万年历的简单实现(案例)

    问题:输入年,月,打印对应年月的日历. 示例: 问题分析: 1,首先1970年是Unix系统诞生的时间,1970年成为Unix的元年,1970年1月1号是星期四,现在大多的手机的日历功能只能显示到1970年1月1日这一天; 2,要想打印某年某月的日历,首先应该计算出这个月1号是星期几? 解决1号是星期几? 2.1:先计算出年天数,即截至这一年1月1号的天数,用for循环,从1970年开始,闰年+366,平年+365; 2.2:计算出月天数,即截至本月1号的天数,用for循环,从1月份开始,算出月

  • JAVA实现的简单万年历代码

    本文实例讲述了JAVA实现的简单万年历.分享给大家供大家参考,具体如下: import java.util.Scanner; public class PrintCalendar { public static void main(String[] args) { int years = 0; int month = 0; int days = 0; boolean isRun = false; //從控制台輸入年,月 Scanner input = new Scanner(System.in)

  • Java 实现万年历总结

    一,Java实现万年历的代码: package calendar; import java.util.Scanner;//日历项目 public class RiLi{ public static void main(String[] args){ Scanner A=new Scanner(System.in); System.out.println("请输入年份:"); int year=A.nextInt(); System.out.println("请输入月份:&qu

  • Java编写多功能万年历程序的实例分享

    这里的万年历制作主要用到了Calendar类和GregorianCalendar类,我们先来回顾一下基础知识: 基础部分 一.Calendar类. 1,主要字段: YEAR(年份).MONTH(月份从0开始).DATE(一月的某天).HOUR(指示上午或下午的小时).HOUR_F_DAY(指示一天中的小时.).DAY_OF_WEEK (一个星期中的某天).DAY_OF_MONTH(一个月中的某天).DAY_OF_YEAR(一年中的某天).DAY_OF_WEEK _IN_MONTH(一个月中的第几

  • Java 实现完整功能的学生管理系统实例

    目录 一.前言 二.学生管理系统主要功能 在学生类下 在学生总部类下: main方法: 登录密码验证: 打印菜单: 增加学生信息: 查看学生信息: 删除学生信息: 修改学生信息: 查找学生信息: 代码效果演示图: 一.前言 我们前面写了通讯录管理系统,现在我们来写个学生管理系统, 其实主干代码都一 不过,在学生管理系统中我添加和优化了许多功能, 如[登录密码验证,异常处理,非空判断,,防止重复添加]等. 二.学生管理系统主要功能 增加学生信息 删除学生信息 修改学生信息 查找学生信息 查看所有学

  • 利用Java编写24点小游戏的实例代码

    话不多说直接给大家上代码 package com.company; import java.util.*; /** * 24点小游戏 * 游戏规则:系统自动生成4个1-10的随机整数,玩家通过加减乘除操作,得到结果为24,每个数字只能使用一次 */ public class Game24Player { final String[] patterns = {"nnonnoo", "nnonono", "nnnoono", "nnnono

  • python编写扎金花小程序的实例代码

    游戏规则: 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢. 有以下几种牌: 豹子:三张一样的牌,如3张6. 顺金:又称同花顺,即3张同样花色的顺子, 如红桃 5.6.7 顺子:又称拖拉机,花色不同,但是顺子,如红桃5.方片6.黑桃7,组成的顺子 对子:2张牌一样 单张:单张最大的是A 这几种牌的大小顺序为, 豹子>顺金>顺子>对子>单张 程序需要实现的点: 先生成一付完整的扑克牌 给5个玩家随机发牌 统一开牌,比大小,输出赢家是谁 主要思路: 把各种牌用积分来计算,

  • Ruby编写HTML脚本替换小程序的实例分享

    在一个文件里有很多以下内容: <p style="display:none">此题选D. .... .... .... </p> 而本人要实现的功能是将它替换成: <div style="display:none" class="sl_explain">此题选D. ..... ..... ..... </div> 这个东西看起来有点简单,但本人整整花了半天才实现此功能,主要是很久没写RUBY程序了,

  • Java防锁屏小程序代码实例

    为防止系统桌面自动锁屏,只需打成jar包,写个批处理程序start.bat,双击执行保持dos窗口执行即可,无其他影响. 程序设计为每30秒动一次鼠标,可根据需要调整. 附代码: package main; import java.awt.AWTException; import java.awt.Dimension; import java.awt.MouseInfo; import java.awt.Point; import java.awt.PointerInfo; import jav

  • Java Applet查找素数小程序代码实例

    1. Applet 这个远古的东西,今天我同学让我帮他看看代码,说applet运行出错.额,反正闲着也是闲着,看看呗 ,结果看到代码... 2.就是实现这破玩意 package calculate; import java.applet.Applet; import java.awt.*; import java.awt.event.*; public abstract class primeNumBetween extends Applet implements ActionListener

  • PHP编写学校网站上新生注册登陆程序的实例分享

    就弄了三个页面: (1).新生信息注册模块(register.php): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text

  • JAVA实现多线程的两种方法实例分享

    java语言已经内置了多线程支持,所有实现Runnable接口的类都可被启动一个新线程,新线程会执行该实例的run()方法,当run()方法执行完毕后,线程就结束了.一旦一个线程执行完毕,这个实例就不能再重新启动,只能重新生成一个新实例,再启动一个新线程. Thread类是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法: 复制代码 代码如下: Thread t = new Thread(); t.start();

  • 使用Python编写简单的端口扫描器的实例分享

    单线程实现 单线程实现道理比较简单,这里尝试Soket连接3389,连接成功说明端口开放,否则说明没有开远程服务.随便修改了一下就ok了,代码如下,最终得到自己的IP地址. #!/usr/bin/env python import socket if __name__=='__main__': port=3389 s=socket.socket() for cnt in range(253,2,-1): address='XXX.XXX.XXX.'+str(cnt) #XXX.XXX.XXX I

随机推荐