All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.erjia.lang.chinese.calendar.ChineseCalendar Maven / Gradle / Ivy

Go to download

Java 开发工具包 ErJia2,是 ErJia 的升级版,向 Kotlin 迁移。“ErJia”,是以作者生活的村落”二甲村”而来,为了纪念这座美好的小村庄,特意将该工具包以“二甲”的拼音命名。

The newest version!
package org.erjia.lang.chinese.calendar;

import org.erjia.lang.helper.StringHelper;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * @author linshuaishuai
 */
public class ChineseCalendar {

    public static enum TianGan {

        JIA ("甲"),
        YI  ("乙"),
        BING("丙"),
        DING("丁"),
        WU  ("戊"),
        JI  ("己"),
        GENG("庚"),
        XIN ("辛"),
        REN ("壬"),
        GUI ("癸");

        private String name;

        TianGan(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static enum DiZhi {

        ZI  ("子"),
        CHOU("丑"),
        YAN ("寅"),
        MAO ("卯"),
        CHEN("辰"),
        SI  ("巳"),
        WU  ("午"),
        WEI ("未"),
        SHEN("申"),
        YOU ("酉"),
        XV  ("戌"),
        HAI ("亥");

        private String name;

        DiZhi(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static enum ShengXiao {

        SHU ("鼠"),
        NIU ("牛"),
        HU  ("虎"),
        TU  ("兔"),
        LONG("龙"),
        SHE ("蛇"),
        MA  ("马"),
        YANG("羊"),
        HOU ("猴"),
        JI  ("鸡"),
        GOU ("狗"),
        ZHU ("猪");

        private String name;

        ShengXiao(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static class Year {
        private int     value;
        private TianGan tg;
        private DiZhi   dz;

        public Year(int value) {

        }

        public int getValue() {
            return value;
        }

        public TianGan getGan() {
            return tg;
        }

        public DiZhi getZhi() {
            return dz;
        }

    }

    private static final long[] lunarInfo = new long[] { 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 };
    private static final int[] year20 = new int[] { 1, 4, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1 };
    private static final int[] year19 = new int[] { 0, 3, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 };
    private static final int[] year2000 = new int[] { 0, 3, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1 };
    private static final String[] nStr1 = new String[] { "", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" };
    private static final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
    private static final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
    private static final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
    private static final String[] solarTerm = new String[] {
            "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨",
            "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑",
            "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
    };
    private static final String[] lFtv = new String[] { "0101*农历春节", "0115 元宵节", "0505 端午节", "0707 七夕情人节", "0815 中秋节", "0909 重阳节", "1208 腊八节", "1224 小年", "0100*除夕" };

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 EEEEE");

    private Calendar gregorianCalendar;

    private ChineseCalendar(Calendar gregorianCalendar) {
        this.gregorianCalendar = gregorianCalendar;
    }


    public static ChineseCalendar getInstance() {
        return new ChineseCalendar(Calendar.getInstance());
    }


    public static ChineseCalendar getInstance(Calendar gregorianCalendar) {
        return new ChineseCalendar(gregorianCalendar);
    }


    /**
     * 计算农历一年的天数
     * @return 该年的天数
     */
    public final int daysOfYear() {
        return daysOfYear(getGregorianYear());
    }


    /**
     * 计算农历闰月的天数
     * @return 该年闰月的天数
     */
    public final int daysOfLeapMonth() {
        return daysOfLeapMonth(getGregorianMonth());
    }


    /**
     * 计算该年闰月的月份(1-12), 没闰月返回 0。
     * @return 该年闰月的月份
     */
    public final int getLeapMonth() {
        return getLeapMonth(getGregorianYear());
    }


    /**
     * 计算该月的总天数
     * @return 该月的天数
     */
    public final int daysOfMonth() {
        return daysOfMonth(getGregorianYear(), getGregorianMonth());
    }


    /**
     * 获得干支年
     * @return 干支年
     */
    public final String getYear() {
        int num = (int) (calElement()[0] - 1900 + 36);
        return (Gan[num % 10] + Zhi[num % 12]);
    }


    /**
     * 获得月份
     * @return 月份
     */
    public final String getMonth() {
        long[] elements = calElement();
        return nStr1[(int) elements[1]];
    }


    /**
     * 获得日
     * @return 日
     */
    public final String getDay() {
        long[] elements = calElement();
        return toChineseDay((int) (elements[2]));
    }


    /**
     * 根据Calendar的字段获取相应的值
     * @param field 字段
     * @return 年/月/日
     */
    public final String get(int field) {
        switch (field) {
            case Calendar.YEAR: return getYear();
            case Calendar.MONTH: return getMonth();
            case Calendar.DAY_OF_MONTH: return getDay();
            default: return null;
        }
    }


    /**
     * 获得生肖
     * @return 生肖
     */
    public final String getZodiac() {
        return Animals[(int) ((calElement()[0] - 4) % 12)];
    }


    /**
     * 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
     *
     * @return
     */
    private long[] calElement() {
        return calElement(getGregorianYear(), getGregorianMonth(), getGregorianDay());
    }


    /**
     * 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
     */
    private long[] calElement(int y, int m, int d) {
        long[] nongDate = new long[7];
        int i = 0, temp = 0, leap = 0;
        Date baseDate = new GregorianCalendar(0 + 1900, 0, 31).getTime();
        Date objDate = new GregorianCalendar(y, m - 1, d).getTime();
        long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;
        nongDate[5] = offset + 40;
        nongDate[4] = 14;
        for (i = 1900; i < 2050 && offset > 0; i++) {
            temp = daysOfYear(i);
            offset -= temp;
            nongDate[4] += 12;
        }
        if (offset < 0) {
            offset += temp;
            i--;
            nongDate[4] -= 12;
        }
        nongDate[0] = i;
        nongDate[3] = i - 1864;
        leap = getLeapMonth(i); // 闰哪个月
        nongDate[6] = 0;
        for (i = 1; i < 13 && offset > 0; i++) {
            // 闰月
            if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {
                --i;
                nongDate[6] = 1;
                temp = daysOfLeapMonth((int) nongDate[0]);
            } else {
                temp = daysOfMonth((int) nongDate[0], i);
            }
            // 解除闰月
            if (nongDate[6] == 1 && i == (leap + 1))
                nongDate[6] = 0;
            offset -= temp;
            if (nongDate[6] == 0)
                nongDate[4]++;
        }
        if (offset == 0 && leap > 0 && i == leap + 1) {
            if (nongDate[6] == 1) {
                nongDate[6] = 0;
            } else {
                nongDate[6] = 1;
                --i;
                --nongDate[4];
            }
        }
        if (offset < 0) {
            offset += temp;
            --i;
            --nongDate[4];
        }
        nongDate[1] = i;
        nongDate[2] = offset + 1;
        return nongDate;
    }


    /**
     * 将公历日的名称转换为阴历日名称
     * @param day 公历日
     * @return 阴历日
     */
    public static String toChineseDay(int day) {
        String result = StringHelper.EMPTY;
        switch (day) {
            case 10: return "初十";
            case 20: return "二十";
            case 30: return "三十";
            default:
                break;
        }
        int two = ((day) / 10);
        switch (two) {
            case 0: result = "初"; break;
            case 1: result = "十"; break;
            case 2: result = "廿"; break;
            case 3: result = "三"; break;
            default:
                break;
        }
        int one = (day % 10);
        switch (one) {
            case 1: result += "一"; break;
            case 2: result += "二"; break;
            case 3: result += "三"; break;
            case 4: result += "四"; break;
            case 5: result += "五"; break;
            case 6: result += "六"; break;
            case 7: result += "七"; break;
            case 8: result += "八"; break;
            case 9: result += "九"; break;
        }
        return result;
    }


    private int getGregorianYear() {
        return gregorianCalendar.get(Calendar.YEAR);
    }


    private int getGregorianMonth() {
        return gregorianCalendar.get(Calendar.MONTH) + 1;
    }


    private int getGregorianDay() {
        return gregorianCalendar.get(Calendar.DAY_OF_MONTH);
    }


    private static int daysOfYear(int year) {
        int i, sum = 348;
        for (i = 0x8000; i > 0x8; i >>= 1) {
            if ((lunarInfo[year - 1900] & i) != 0)
                sum += 1;
        }
        return (sum + daysOfLeapMonth(year));
    }


    private static int daysOfLeapMonth(int year) {
        if (getLeapMonth(year) != 0) {
            if ((lunarInfo[year - 1900] & 0x10000) != 0) {
                return 30;
            }
            else {
                return 29;
            }
        } else {
            return 0;
        }
    }


    private static int getLeapMonth(int year) {
        return (int) (lunarInfo[year - 1900] & 0xf);
    }


    private static int daysOfMonth(int year, int month) {
        if ((lunarInfo[year - 1900] & (0x10000 >> month)) == 0) {
            return 29;
        } else {
            return 30;
        }
    }


    @Override
    public final String toString() {
        long[] l = calElement();
        StringBuilder sToday = new StringBuilder();
        sToday.append(getYear());
        sToday.append('(');
        sToday.append(getZodiac());
        sToday.append(")年");
        sToday.append(getMonth());
        sToday.append("月");
        if (l[6] == 1) {
            sToday.append("(润)");
        }
        sToday.append(toChineseDay((int) (l[2])));
        return sToday.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy