java 实现二十四节气

直接贴代码

public class _24SolarTerms {
    private static final double D = 0.2422;
    private final static Map<String, Integer[]> INCREASE_OFFSETMAP = new HashMap<String, Integer[]>();// +1偏移
    private final static Map<String, Integer[]> DECREASE_OFFSETMAP = new HashMap<String, Integer[]>();// -1偏移

    /** 24节气 **/
    private static enum SolarTermsEnum {
        LICHUN, // --立春
        YUSHUI, // --雨水
        JINGZHE, // --惊蛰
        CHUNFEN, // 春分
        QINGMING, // 清明
        GUYU, // 谷雨
        LIXIA, // 立夏
        XIAOMAN, // 小满
        MANGZHONG, // 芒种
        XIAZHI, // 夏至
        XIAOSHU, // 小暑
        DASHU, // 大暑
        LIQIU, // 立秋
        CHUSHU, // 处暑
        BAILU, // 白露
        QIUFEN, // 秋分
        HANLU, // 寒露
        SHUANGJIANG, // 霜降
        LIDONG, // 立冬
        XIAOXUE, // 小雪
        DAXUE, // 大雪
        DONGZHI, // 冬至
        XIAOHAN, // 小寒
        DAHAN;// 大寒
    }

    static {
        DECREASE_OFFSETMAP.put(SolarTermsEnum.YUSHUI.name(),
                new Integer[] { 2026 });// 雨水
        INCREASE_OFFSETMAP.put(SolarTermsEnum.CHUNFEN.name(),
                new Integer[] { 2084 });// 春分
        INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOMAN.name(),
                new Integer[] { 2008 });// 小满
        INCREASE_OFFSETMAP.put(SolarTermsEnum.MANGZHONG.name(),
                new Integer[] { 1902 });// 芒种
        INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAZHI.name(),
                new Integer[] { 1928 });// 夏至
        INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOSHU.name(), new Integer[] {
                1925, 2016 });// 小暑
        INCREASE_OFFSETMAP.put(SolarTermsEnum.DASHU.name(),
                new Integer[] { 1922 });// 大暑
        INCREASE_OFFSETMAP.put(SolarTermsEnum.LIQIU.name(),
                new Integer[] { 2002 });// 立秋
        INCREASE_OFFSETMAP.put(SolarTermsEnum.BAILU.name(),
                new Integer[] { 1927 });// 白露
        INCREASE_OFFSETMAP.put(SolarTermsEnum.QIUFEN.name(),
                new Integer[] { 1942 });// 秋分
        INCREASE_OFFSETMAP.put(SolarTermsEnum.SHUANGJIANG.name(),
                new Integer[] { 2089 });// 霜降
        INCREASE_OFFSETMAP.put(SolarTermsEnum.LIDONG.name(),
                new Integer[] { 2089 });// 立冬
        INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOXUE.name(),
                new Integer[] { 1978 });// 小雪
        INCREASE_OFFSETMAP.put(SolarTermsEnum.DAXUE.name(),
                new Integer[] { 1954 });// 大雪
        DECREASE_OFFSETMAP.put(SolarTermsEnum.DONGZHI.name(), new Integer[] {
                1918, 2021 });// 冬至

        INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(),
                new Integer[] { 1982 });// 小寒
        DECREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(),
                new Integer[] { 2019 });// 小寒

        INCREASE_OFFSETMAP.put(SolarTermsEnum.DAHAN.name(),
                new Integer[] { 2082 });// 大寒
    }

    // 定义一个二维数组,第一维数组存储的是20世纪的节气C值,第二维数组存储的是21世纪的节气C值,0到23个,依次代表立春、雨水...大寒节气的C值
    private static final double[][] CENTURY_ARRAY = {
            { 4.6295, 19.4599, 6.3826, 21.4155, 5.59, 20.888, 6.318, 21.86,
                    6.5, 22.2, 7.928, 23.65, 8.35, 23.95, 8.44, 23.822, 9.098,
                    24.218, 8.218, 23.08, 7.9, 22.6, 6.11, 20.84 },
            { 3.87, 18.73, 5.63, 20.646, 4.81, 20.1, 5.52, 21.04, 5.678, 21.37,
                    7.108, 22.83, 7.5, 23.13, 7.646, 23.042, 8.318, 23.438,
                    7.438, 22.36, 7.18, 21.94, 5.4055, 20.12 } };

    /**
     * 
     * @param year
     *            年份
     * @param name
     *            节气的名称
     * @return 返回节气是相应月份的第几天
     */
    public static int getSolarTermNum(int year, String name) {

        double centuryValue = 0;// 节气的世纪值,每个节气的每个世纪值都不同
        name = name.trim().toUpperCase();
        int ordinal = SolarTermsEnum.valueOf(name).ordinal();

        int centuryIndex = -1;
        if (year >= 1901 && year <= 2000) {// 20世纪
            centuryIndex = 0;
        } else if (year >= 2001 && year <= 2100) {// 21世纪
            centuryIndex = 1;
        } else {
            throw new RuntimeException("不支持此年份:" + year
                    + ",目前只支持1901年到2100年的时间范围");
        }
        centuryValue = CENTURY_ARRAY[centuryIndex][ordinal];
        int dateNum = 0;
        /**
         * 计算 num =[Y*D+C]-L这是传说中的寿星通用公式
         * 公式解读:年数的后2位乘0.2422加C(即:centuryValue)取整数后,减闰年数
         */
        int y = year % 100;// 步骤1:取年分的后两位数
        if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {// 闰年
            if (ordinal == SolarTermsEnum.XIAOHAN.ordinal()
                    || ordinal == SolarTermsEnum.DAHAN.ordinal()
                    || ordinal == SolarTermsEnum.LICHUN.ordinal()
                    || ordinal == SolarTermsEnum.YUSHUI.ordinal()) {
                // 注意:凡闰年3月1日前闰年数要减一,即:L=[(Y-1)/4],因为小寒、大寒、立春、雨水这两个节气都小于3月1日,所以
                // y = y-1
                y = y - 1;// 步骤2
            }
        }
        dateNum = (int) (y * D + centuryValue) - (int) (y / 4);// 步骤3,使用公式[Y*D+C]-L计算
        dateNum += specialYearOffset(year, name);// 步骤4,加上特殊的年分的节气偏移量
        return dateNum;
    }

    /**
     * 特例,特殊的年分的节气偏移量,由于公式并不完善,所以算出的个别节气的第几天数并不准确,在此返回其偏移量
     * 
     * @param year
     *            年份
     * @param name
     *            节气名称
     * @return 返回其偏移量
     */
    private static int specialYearOffset(int year, String name) {
        int offset = 0;
        offset += getOffset(DECREASE_OFFSETMAP, year, name, -1);
        offset += getOffset(INCREASE_OFFSETMAP, year, name, 1);

        return offset;
    }

    private static int getOffset(Map<String, Integer[]> map, int year,
            String name, int offset) {
        int off = 0;
        Integer[] years = map.get(name);
        if (null != years) {
            for (int i : years) {
                if (i == year) {
                    off = offset;
                    break;
                }
            }
        }
        return off;
    }

    private static int mYear;
    private static List<String> mSolarData = new ArrayList<String>();
    private static List<String> mSolarName = new ArrayList<String>();
/**
 * 判断一天是什么节气
 * @data2015-12-2下午2:49:32
 * @param year 
 * @param data 月份占两位,日不确定,如一月一日为:011,五月十日为0510
 * @return
 */
    public static String getSolatName(int year, String data) {
        if (year != mYear) {
            solarTermToString(year);
        }
        if (mSolarData.contains(data)) {
            return mSolarName.get(mSolarData.indexOf(data));
        } else {
            return null;
        }
    }

    private static void solarTermToString(int year) {
        mYear = year;
        if (mSolarData != null) {
            mSolarData.clear();
        } else {
            mSolarData = new ArrayList<String>();
        }
        if (mSolarName != null) {
            mSolarName.clear();
        } else {
            mSolarName = new ArrayList<String>();
        }
        // 1
        mSolarName.add("立春");
        mSolarData.add("02"
                + getSolarTermNum(year, SolarTermsEnum.LICHUN.name()));
        // 2
        mSolarName.add("雨水");
        mSolarData.add("02"
                + getSolarTermNum(year, SolarTermsEnum.YUSHUI.name()));
        // 3
        mSolarName.add("惊蛰");
        mSolarData.add("03"
                + getSolarTermNum(year, SolarTermsEnum.JINGZHE.name()));
        // 4
        mSolarName.add("春分");
        mSolarData.add("03"
                + getSolarTermNum(year, SolarTermsEnum.CHUNFEN.name()));
        // 5
        mSolarName.add("清明");
        mSolarData.add("04"
                + getSolarTermNum(year, SolarTermsEnum.QINGMING.name()));
        // 6
        mSolarName.add("谷雨");
        mSolarData.add("04" + getSolarTermNum(year, SolarTermsEnum.GUYU.name()));
        // 7
        mSolarName.add("立夏");
        mSolarData
                .add("05" + getSolarTermNum(year, SolarTermsEnum.LIXIA.name()));
        // 8
        mSolarName.add("小满");
        mSolarData.add("05"
                + getSolarTermNum(year, SolarTermsEnum.XIAOMAN.name()));
        // 9
        mSolarName.add("芒种");
        mSolarData.add("06"
                + getSolarTermNum(year, SolarTermsEnum.MANGZHONG.name()));
        // 10
        mSolarName.add("夏至");
        mSolarData.add("06"
                + getSolarTermNum(year, SolarTermsEnum.XIAZHI.name()));
        // 11
        mSolarName.add("小暑");
        mSolarData.add("07"
                + getSolarTermNum(year, SolarTermsEnum.XIAOSHU.name()));
        // 12
        mSolarName.add("大暑");
        mSolarData
                .add("07" + getSolarTermNum(year, SolarTermsEnum.DASHU.name()));
        // 13
        mSolarName.add("立秋");
        mSolarData
                .add("08" + getSolarTermNum(year, SolarTermsEnum.LIQIU.name()));
        // 14
        mSolarName.add("处暑");
        mSolarData.add("08"
                + getSolarTermNum(year, SolarTermsEnum.CHUSHU.name()));
        // 15
        mSolarName.add("白露");
        mSolarData
                .add("09" + getSolarTermNum(year, SolarTermsEnum.BAILU.name()));
        // 16
        mSolarName.add("秋分");
        mSolarData.add("09"
                + getSolarTermNum(year, SolarTermsEnum.QIUFEN.name()));
        // 17
        mSolarName.add("寒露");
        mSolarData.add("10"
                + getSolarTermNum(year, SolarTermsEnum.HANLU.name()));
        // 18
        mSolarName.add("霜降");
        mSolarData.add("10"
                + getSolarTermNum(year, SolarTermsEnum.SHUANGJIANG.name()));
        // 19
        mSolarName.add("立冬");
        mSolarData.add("11"
                + getSolarTermNum(year, SolarTermsEnum.LIDONG.name()));
        // 20
        mSolarName.add("小雪");
        mSolarData.add("11"
                + getSolarTermNum(year, SolarTermsEnum.XIAOXUE.name()));
        // 21
        mSolarName.add("大雪");
        mSolarData.add("12"
                + getSolarTermNum(year, SolarTermsEnum.DAXUE.name()));
        // 22
        mSolarName.add("冬至");
        mSolarData.add("12"
                + getSolarTermNum(year, SolarTermsEnum.DONGZHI.name()));
        // 23
        mSolarName.add("小寒");
        mSolarData.add("01"
                + getSolarTermNum(year, SolarTermsEnum.XIAOHAN.name()));
        // 24
        mSolarName.add("大寒");
        mSolarData
                .add("01" + getSolarTermNum(year, SolarTermsEnum.DAHAN.name()));

    }

}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值