欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java日期时间API系列11-----Jdk8中java.time包中的新的日期时间API类,使用java8日期时间API重写农历LunarDate

程序员文章站 2022-06-05 17:32:59
通过Java日期时间API系列7 Jdk8中java.time包中的新的日期时间API类的优点,java8具有很多优点,现在网上查到的农历转换工具类都是基于jdk7及以前的类写的,下面使用java新的日期时间API重写农历LunarDate。 package com.xkzhangsan.time; ......

  通过java日期时间api系列7-----jdk8中java.time包中的新的日期时间api类的优点,java8具有很多优点,现在网上查到的农历转换工具类都是基于jdk7及以前的类写的,下面使用java新的日期时间api重写农历lunardate。

package com.xkzhangsan.time;

import java.time.instant;
import java.time.localdate;
import java.time.localdatetime;
import java.util.date;

import com.xkzhangsan.time.converter.datetimeconverterutil;

/**
 * 农历日期
* @classname: lunardate 
* @description: lunardate
* @author xkzhangsan
* @date 2019年12月30日
* @version 0.1 ,初版,谨慎试用
 */
public final class lunardate {
    
    /**
     * 农历信息
     */
    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 };

    /**
     * 农历月份列表
     */
    public static final string[] lunarmonth = new string[] { "", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬",
            "腊" };
    /**
     * 天干列表
     */
    private static final string[] tiangan = new string[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };

    /**
     * 地支列表
     */
    private static final string[] dizhi = new string[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };

    /**
     * 生肖列表
     */
    private static final string[] animals = new string[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };

    /**
     * 中文数字0-9
     */
    public static final string[] numstr = new string[] { "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九"};    

    /**
     * 标准日期
     */
    private final localdate localdate;

    /**
     * 农历日期,中文
     */
    private string ldatecn;

    /**
     * 岁次
     */
    private string suici;

    /**
     * 生肖
     */
    private string lanimal;

    /**
     * 农历年
     */
    private int lyear;

    /**
     * 农历月
     */
    private int lmonth;

    /**
     * 农历日
     */
    private int lday;

    /**
     * 农历年,中文
     */
    private string lyearcn;

    /**
     * 农历月,中文
     */
    private string lmonthcn;

    /**
     * 农历日,中文
     */
    private string ldaycn;

    /**
     * 星期,中文
     */
    private string weekcn;

    private lunardate(localdate localdate) {
        super();
        this.localdate = localdate;
        initialize();
    }
    
    /**
     * 初始化农历日期
     */
    public void initialize() {
        int year = localdate.getyear();
        int month = localdate.getmonthvalue();
        int day = localdate.getdayofmonth();
        long[] l = calelement(year, month, day);
        
        this.suici = cyclical(year);
        this.lanimal = animalsyear(year);

        this.lyear = (int) l[0];
        this.lmonth = (int) l[1];
        this.lday = (int) l[2];

        this.lyearcn = getchinayear(this.lyear);
        this.lmonthcn = lunarmonth[this.lmonth];
        this.ldaycn = getchinaday(this.lday);

        this.weekcn = getweekcn(localdate.getdayofweek().getvalue());
        this.ldatecn = this.lyearcn + "年" + this.lmonthcn + "月" + this.ldaycn;
    }
    
    /**
     * 通过localdatetime创建lunardate
     * @param localdatetime
     * @return
     */
    public static lunardate from(localdatetime localdatetime) {
        return new lunardate(datetimeconverterutil.tolocaldate(localdatetime));
    }

    /**
     * 通过localdate创建lunardate
     * @param localdate
     * @return
     */
    public static lunardate from(localdate localdate) {
        return new lunardate(localdate);
    }
    
    /**
     * 通过instant创建lunardate
     * @param localdate
     * @return
     */
    public static lunardate from(instant instant) {
        return new lunardate(datetimeconverterutil.tolocaldate(instant));
    }    

    /**
     * 通过date创建lunardate
     * @param date
     * @return
     */
    public static lunardate from(date date) {
        return new lunardate(datetimeconverterutil.tolocaldate(date));
    }

    /**
     * 传回农历year年的总天数
     *
     * @param year
     * @return
     */
    private static final int lunaryeardays(int year) {
        int i, sum = 348;
        for (i = 0x8000; i > 0x8; i >>= 1) {
            if ((lunarinfo[year - 1900] & i) != 0)
                sum += 1;
        }
        return (sum + leapmonthdays(year));
    }

    /**
     * 传回农历 year年闰月的天数
     *
     * @param year
     * @return
     */
    private static final int leapmonthdays(int year) {
        if (leapmonth(year) != 0) {
            if ((lunarinfo[year - 1900] & 0x10000) != 0)
                return 30;
            else
                return 29;
        } else
            return 0;
    }

    /**
     * 传回农历 year年闰哪个月 1-12 , 没闰传回 0
     *
     * @param year
     * @return
     */
    private static final int leapmonth(int year) {
        return (int) (lunarinfo[year - 1900] & 0xf);
    }

    /**
     * 传回农历 year年month月的总天数
     *
     * @param year
     * @param month
     * @return
     */
    private static final int monthdays(int year, int month) {
        if ((lunarinfo[year - 1900] & (0x10000 >> month)) == 0)
            return 29;
        else
            return 30;
    }

    /**
     * 传回农历 year年的生肖
     *
     * @param year
     * @return
     */
    public static final string animalsyear(int year) {
        return animals[(year - 4) % 12];
    }

    /**
     * 传入 月日的offset 传回干支,0=甲子
     *
     * @param num
     * @return
     */
    private static final string cyclicalm(int num) {
        return (tiangan[num % 10] + dizhi[num % 12]);
    }

    /**
     * 传入 offset 传回干支, 0=甲子
     *
     * @param year
     * @return
     */
    public static final string cyclical(int year) {
        int num = year - 1900 + 36;
        return (cyclicalm(num));
    }

    /**
     * 传出year年month月day日对应的农历.year0 .month1 .day2 .yearcyl3 .moncyl4 .daycyl5
     * .isleap6
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static final long[] calelement(int year, int month, int day) {
        long[] nongdate = new long[7];
        int i = 0, temp = 0, leap = 0;
        localdate basedate = localdate.of(0 + 1900, 1, 31);
        localdate objdate = localdate.of(year, month, day);
        long offset = (datetimeconverterutil.toepochmilli(objdate) - datetimeconverterutil.toepochmilli(basedate))
                / 86400000l;
        nongdate[5] = offset + 40;
        nongdate[4] = 14;
        for (i = 1900; i < 2050 && offset > 0; i++) {
            temp = lunaryeardays(i);
            offset -= temp;
            nongdate[4] += 12;
        }
        if (offset < 0) {
            offset += temp;
            i--;
            nongdate[4] -= 12;
        }
        nongdate[0] = i;
        nongdate[3] = i - 1864;
        leap = leapmonth(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 = leapmonthdays((int) nongdate[0]);
            } else {
                temp = monthdays((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;
    }

    public final static string getchinayear(int year) {
        string ge = numstr[year % 10];
        string shi = numstr[year / 10 % 10];
        string bai = numstr[year / 100 % 10];
        string qian = numstr[year / 1000 % 10];
        return qian + bai + shi + ge;
    }

    public final static string getchinaday(int day) {
        string a = "";
        if (day == 10)
            return "初十";
        if (day == 20)
            return "二十";
        if (day == 30)
            return "三十";
        int two = (int) ((day) / 10);
        if (two == 0)
            a = "初";
        if (two == 1)
            a = "十";
        if (two == 2)
            a = "廿";
        if (two == 3)
            a = "三";
        int one = (int) (day % 10);
        switch (one) {
        case 1:
            a += "一";
            break;
        case 2:
            a += "二";
            break;
        case 3:
            a += "三";
            break;
        case 4:
            a += "四";
            break;
        case 5:
            a += "五";
            break;
        case 6:
            a += "六";
            break;
        case 7:
            a += "七";
            break;
        case 8:
            a += "八";
            break;
        case 9:
            a += "九";
            break;
        default:
            a += "";
            break;
        }
        return a;
    }
    
    public final static string getweekcn(int week) {
        string weekcn = "";
        switch (week) {
        case 1:
            weekcn = "星期一";
            break;
        case 2:
            weekcn = "星期二";
            break;
        case 3:
            weekcn = "星期三";
            break;
        case 4:
            weekcn = "星期四";
            break;
        case 5:
            weekcn = "星期五";
            break;
        case 6:
            weekcn = "星期六";
            break;
        case 7:
            weekcn = "星期日";
            break;
        default:
            weekcn = "";
            break;
        }
        return weekcn;
    }

    public static lunardate today() {
        localdate today = localdate.now();
        return new lunardate(today);
    }

    public localdate getlocaldate() {
        return localdate;
    }

    public string getdatecn() {
        return ldatecn;
    }

    public string getsuici() {
        return suici;
    }

    public string getlanimalcn() {
        return lanimal;
    }

    public int getlyear() {
        return lyear;
    }

    public int getlmonth() {
        return lmonth;
    }

    public int getlday() {
        return lday;
    }

    public string getlyearcn() {
        return lyearcn;
    }

    public string getlmonthcn() {
        return lmonthcn;
    }

    public string getldaycn() {
        return ldaycn;
    }

    public string getweekcn() {
        return weekcn;
    }

    @override
    public string tostring() {
        return "lunardate [localdate=" + localdate + ",ldatecn=" + ldatecn + ", suici=" + suici + ", lanimal=" + lanimal + ", lyear=" + lyear
                + ", lmonth=" + lmonth + ", lday=" + lday + ", lyearcn=" + lyearcn + ", lmonthcn=" + lmonthcn
                + ", ldaycn=" + ldaycn + ", weekcn=" + weekcn + "]";
    }


    public static void main(string[] args) {
        string str =lunardate.today().tostring();
        system.out.println(str);
    }
}

 

输出为:

lunardate [localdate=2019-12-30,ldatecn=二〇一九年腊月初五, suici=己亥, lanimal=猪, lyear=2019, lmonth=12, lday=5, lyearcn=二〇一九, lmonthcn=腊, ldaycn=初五, weekcn=星期一]

 

农历原始算法来自网络。

 

源码地址: