Java日期時間API系列28-----Jdk8中java.time包中的新的日期時間API類,計算節假日和二十四節氣。


1.節日信息計算代碼

package com.xkzhangsan.time.holiday;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.MonthDay;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;

import com.xkzhangsan.time.LunarDate;
import com.xkzhangsan.time.constants.Constant;
import com.xkzhangsan.time.converter.DateTimeConverterUtil;
import com.xkzhangsan.time.formatter.DateTimeFormatterUtil;
import com.xkzhangsan.time.utils.CollectionUtil;
import com.xkzhangsan.time.utils.StringUtil;

/**
 * 節日處理
 * 包含
 * 1.公歷節假日計算, getLocalHoliday* 比如getLocalHoliday(Date date) 計算date的公歷節日,getLocalHoliday(Date date, Map<String, String> localHolidayMap) 可以傳入自定義公歷節日數據
 * 2.農歷節假日計算, getChineseHoliday* 比如getChineseHoliday(Date date) 計算date的農歷節日,getChineseHoliday(Date date, Map<String, String> chineseHolidayMap) 可以傳入自定義農歷節日數據
 * 3.二十四節氣計算, getSolarTerm* 比如getSolarTerm(Date date) 計算date的二十四節氣
 * 
 * 農歷相關,僅支持公歷1901-2050年的計算
* @ClassName: Holiday
* @Description: Holiday
* @author xkzhangsan
* @date 2019年12月30日
* @version 0.2 試用
 */
public interface Holiday {
    
    /**
     * 根據日期獲取公歷節日
     * @param date
     * @return
     */
    static String getLocalHoliday(Date date){
        return getLocalHoliday(date, null);
    }
    
    /**
     * 根據日期獲取公歷節日
     * @param date
     * @param localHolidayMap 自定義節日數據,特殊節日如,"母親節", "5-W-2-7" 5表示5月,W表示星期,2表示第二個星期,7表示星期的第7天
     * @return
     */
    static String getLocalHoliday(Date date, Map<String, String> localHolidayMap){
        Objects.requireNonNull(date, "date");
        return getLocalHoliday(DateTimeConverterUtil.toLocalDateTime(date), localHolidayMap);
    }
    
    /**
     * 根據日期獲取公歷節日
     * @param temporal 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime
     * @return
     */
    static String getLocalHoliday(Temporal temporal){
        return getLocalHoliday(temporal, null);
    }
    
    /**
     * 根據日期獲取公歷節日
     * @param temporal 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime
     * @param localHolidayMap 自定義節日數據,特殊節日如,"母親節", "5-W-2-7" 5表示5月,W表示星期,2表示第二個星期,7表示星期的第7天
     * @return
     */
    static String getLocalHoliday(Temporal temporal, Map<String, String> localHolidayMap){
        Objects.requireNonNull(temporal, "temporal");
        String localHoliday = "";
        if(CollectionUtil.isEmpty(localHolidayMap)){
            localHolidayMap = LocalHolidayEnum.convertToMap();
        }
        
        MonthDay monthDay = MonthDay.from(temporal);
        String monthDayStr = monthDay.format(DateTimeFormatterUtil.MMDD_FMT);
        for(Entry<String, String> entry : localHolidayMap.entrySet()){
            if (entry.getKey().equals(monthDayStr)) {
                if(StringUtil.isEmpty(localHoliday)){
                    localHoliday = entry.getValue();
                }else{
                    localHoliday = localHoliday + " " +entry.getValue();
                }
            }
            //如果為特殊格式,解析對比
            if (entry.getKey().contains("W")) {
                String[] arr = entry.getKey().split("-");
                int month = Integer.parseInt(arr[0]);
                int weekIndex = Integer.parseInt(arr[2]);
                int weekValue = Integer.parseInt(arr[3]);
                DayOfWeek dow = DayOfWeek.of(weekValue);
                //設置到當前節日的月份
                Temporal tempTem = temporal.with(ChronoField.MONTH_OF_YEAR, month);
                //設置到當前節日的第幾星期第幾天
                Temporal targetTem = tempTem.with(TemporalAdjusters.dayOfWeekInMonth(weekIndex, dow));
                MonthDay targetMonthDay = MonthDay.from(targetTem);
                String targetMonthDayStr = targetMonthDay.format(DateTimeFormatterUtil.MMDD_FMT);
                if (monthDayStr.equals(targetMonthDayStr)) {
                    if(StringUtil.isEmpty(localHoliday)){
                        localHoliday = entry.getValue();
                    }else{
                        localHoliday = localHoliday + " " +entry.getValue();
                    }
                }
            }
        }
        return localHoliday;
    }
    
    /**
     * 根據日期獲取農歷幾日
     * @param date
     * @return
     */
    static String getChineseHoliday(Date date){
        return getChineseHoliday(date, null);
    }
    
    /**
     * 根據日期獲取農歷幾日
     * @param date
     * @param chineseHolidayMap 自定義節日數據,特殊節日如除夕 用CHUXI表示
     * @return
     */
    static String getChineseHoliday(Date date, Map<String, String> chineseHolidayMap){
        Objects.requireNonNull(date, "date");
        return getChineseHoliday(DateTimeConverterUtil.toLocalDateTime(date), chineseHolidayMap);
    }
    
    /**
     * 根據日期獲取農歷幾日
     * @param temporal 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime
     * @return
     */
    static String getChineseHoliday(Temporal temporal){
        return getChineseHoliday(temporal, null);
    }
    
    /**
     * 根據日期獲取農歷幾日
     * @param temporal 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime
     * @param chineseHolidayMap 自定義節日數據,特殊節日如除夕 用CHUXI表示
     * @return
     */
    static String getChineseHoliday(Temporal temporal, Map<String, String> chineseHolidayMap){
        Objects.requireNonNull(temporal, "temporal");
        String chineseHoliday = "";
        if(CollectionUtil.isEmpty(chineseHolidayMap)){
            chineseHolidayMap = ChineseHolidayEnum.convertToMap();
        }
        
        LunarDate lunarDate = LunarDate.from(temporal);
        
        //閏月不計算節假日
        if(StringUtil.isNotEmpty(lunarDate.getLeapMonthCn())){
            return chineseHoliday;
        }
        String monthDayStr = lunarDate.formatShort();
        //對比枚舉日期,返回假日
        for(Entry<String, String> entry : chineseHolidayMap.entrySet()){
            if (entry.getKey().equals(monthDayStr)) {
                if(StringUtil.isEmpty(chineseHoliday)){
                    chineseHoliday = entry.getValue();
                }else{
                    chineseHoliday = chineseHoliday + " " +entry.getValue();
                }
            }
            //如果為特殊節日除夕
            if (entry.getKey().equals(Constant.CHUXI)) {
                LocalDate tempLocalDate = lunarDate.getLocalDate();
                LocalDate targetLocalDate = tempLocalDate.plus(1, ChronoUnit.DAYS);
                LunarDate targetLunarDate = LunarDate.from(targetLocalDate);
                String targetMonthDayStr = targetLunarDate.formatShort();
                if(Constant.CHUNJIE.equals(targetMonthDayStr)){
                    if(StringUtil.isEmpty(chineseHoliday)){
                        chineseHoliday = entry.getValue();
                    }else{
                        chineseHoliday = chineseHoliday + " " +entry.getValue();
                    }
                }
            }
        }
        return chineseHoliday;
    }
    
    /**
     * 根據日期獲取二十四節氣
     * @param date
     * @return
     */
    static String getSolarTerm(Date date){
        Objects.requireNonNull(date, "date");
        LunarDate lunarDate = LunarDate.from(date);
        return lunarDate.getSolarTerm();
    }
    
    /**
     * 根據日期獲取二十四節氣
     * @param temporal 支持 LocalDate、LocalDateTime、Instant和ZonedDateTime
     * @return
     */
    static String getSolarTerm(Temporal temporal){
        Objects.requireNonNull(temporal, "temporal");
        LunarDate lunarDate = LunarDate.from(temporal);
        return lunarDate.getSolarTerm();
    }
}

(1)getLocalHoliday(Date date, Map<String, String> localHolidayMap)中"母親節", "5-W-2-7" 5表示5月,W表示星期,2表示第二個星期,7表示星期的第7天。

使用臨時變量,修改月份為5月,然后使用TemporalAdjusters.dayOfWeekInMonth來計算當前月第幾周第幾天的日期和傳入日期對比。

 

(2)getChineseHoliday(Date date, Map<String, String> chineseHolidayMap) 特殊節日如除夕 用CHUXI

除夕是一年的最后一天和閏年2月類似,具體日期不確定,使用臨時變量,當前日期加一天后為春節,則傳入日期為除夕。

 

(3)getSolarTerm(Date date)

這里使用LunarDate lunarDate = LunarDate.from(date),將當前日期轉換為農歷日期,獲取它的節氣信息。

具體可以看Java日期時間API系列11-----Jdk8中java.time包中的新的日期時間API類,使用java8日期時間API重寫農歷LunarDate 的calElement(int, int, int)方法。

 

2.測試代碼

    /**
     * 公歷節日,母親節
     */
    @Test
    public void localHolidayEnumTest(){
        LocalDate localDate = LocalDate.of(2020, 5, 10);
        System.out.println(Holiday.getLocalHoliday(localDate));
        
        //自定義節日數據
        Map<String, String> localHolidayMap = new HashMap<String, String>();
        localHolidayMap.put("0422", "世界地球日");
        LocalDate localDate2 = LocalDate.of(2020, 4, 22);
        System.out.println(Holiday.getLocalHoliday(localDate2, localHolidayMap));
    }
    
    /**
     * 農歷節日,除夕
     */
    @Test
    public void chineseHolidayEnumTest(){
        LocalDate localDate = LocalDate.of(2020, 1, 24);
        System.out.println("localDate:"+Holiday.getChineseHoliday(localDate));
        
        //正常農歷九月初九
        LocalDate localDate2 = LocalDate.of(2014, 10, 2);
        System.out.println("localDate2:"+Holiday.getChineseHoliday(localDate2));
        
        //正常農歷閏九月初九  閏月不算節假日
        LocalDate localDate3 = LocalDate.of(2014, 11, 1);
        System.out.println("localDate3:"+Holiday.getChineseHoliday(localDate3));
    }
    
    /**
     * 二十四節氣,2020-08-07 立秋
     */
    @Test
    public void solarTermEnumTest(){
        LocalDate localDate = LocalDate.of(2020, 8, 7);
        System.out.println(Holiday.getSolarTerm(localDate));
    }

 

輸出:

母親節
世界地球日

localDate:除夕
localDate2:重陽節
localDate3:

立秋

 

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

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM