Java日期時間API系列11-----Jdk8中java.time包中的新的日期時間API類,使用java8日期時間API重寫農曆LunarDate

来源:https://www.cnblogs.com/xkzhangsanx/archive/2019/12/30/12113506.html
-Advertisement-
Play Games

通過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=星期一]

 

農曆原始演算法來自網路。

 

源碼地址:https://github.com/xkzhangsan/xk-time


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript事件綁定常用方法 對象.事件 = 函數; 它只能同時為一個對象的一個事件綁定一個響應函數 不能綁定多個,如果有多個,後面的會覆蓋前面的 addEventListener() 此方法也可以為元素綁定響應函數 參數: 1. 事件的字元串(不帶on) 2. 回調函數,事件觸發時執行 3 ...
  • CSS中定位介紹 屬性在英文單詞中表示 的意思,在 中主要作用設置元素的定位。 中一共有 種定位如下: 屬性值 | 描述 | fixed | 設置固定定位。 relative | 設置相對定位。 absolute|設置絕對定位。 固定定位實踐 在實踐固定定位之前我們先看看代碼結構是什麼樣子的呢。 代 ...
  • axios 是一個輕量的 HTTP客戶端,它基於 XMLHttpRequest 服務來執行 HTTP 請求,支持豐富的配置,支持 Promise,支持瀏覽器端和 Node.js 端。在真實項目中為了提高我們的代碼質量,我們通常會對 axios 二次封裝一下再使用。這篇文章就帶你從零開始封裝 axio... ...
  • float實現文字環繞圖片效果: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>float</title> <style> body{ font-family: '微軟雅黑'; } .per{ width: ...
  • border-style的值: none 無 dotted 點狀 dashed 虛線 solid 實線 double 雙實線 margin: 垂直方向兩個相鄰元素都設置了外邊距,那麼外邊距會發生合併 合併高度=兩個發生合併的外邊距中的較大值 元素的實際高度=上邊框+上內邊距+內容高度+下內邊距+下邊 ...
  • 1、計算當前周一到周日的日期 ...
  • 1+x證書Web 前端開發初級——理論考試(試卷1) 一、單選題(每小題 2 分,共 30 小題,共 60 分) 1.HTML 語言中,設置表格中文字與邊框距離的標簽是() A、<table boder=””> B、<table cellspacing=””> C、<table cellpaddin ...
  • 對事件作出反應 JavaScript 能夠在事件發生時執行,比如當用戶點擊某個 HTML 元素時。 為了在用戶點擊元素時執行代碼,請向 HTML 事件屬性添加 JavaScript 代碼: HTML 事件的例子: 當用戶點擊滑鼠時 當網頁載入後 當圖像載入後 當滑鼠移至元素上時 當輸入欄位被改變時 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...