Java日期时间API系列25—–Jdk8中java.time包中的新的日期时间API类,使用MonthDay计算十二星座。

  通过Java日期时间API系列24—–Jdk8中java.time包中的新的日期时间API类,MonthDay类源码和应用,对比相同月日时间。对MonthDay简单做了说明和应用。十二星座是根据公历生日类计算属于哪个星座(白羊座、金牛座、双子座、巨蟹座、狮子座、处女座、天秤座、天蝎座、射手座、摩羯座、水瓶座、双鱼座)。

1.十二星座名称枚举

package com.xkzhangsan.time.enums;

import static com.xkzhangsan.time.constants.Constant.MONTHDAY_FORMAT_PRE;

import java.time.MonthDay;
import java.util.Objects;

/**
 * 星座名称枚举,包含英文全称,中文全称,时间范围
 * 
 * @ClassName: ConstellationNameEnum
 * @Description: ConstellationNameEnum
 * @author xkzhangsan
 * @date 2020年02-29
 */
public enum ConstellationNameEnum {
    
    Aries(1, "白羊座", "03-21", "04-19"),
    Taurus(2, "金牛座", "04-20", "05-20"),
    Gemini(3, "双子座", "05-21", "06-21"),
    Cancer(4, "巨蟹座", "06-22", "07-22"),
    Leo(5, "狮子座", "07-23", "08-22"),
    Virgo(6, "处女座", "08-23", "09-22"),
    Libra(7, "天秤座", "09-23", "10-23"), 
    Scorpio(8, "天蝎座", "10-24", "11-22"),
    Sagittarius(9, "射手座", "11-23", "12-21"),
    Capricorn(10, "摩羯座", "12-22", "01-19"),
    Aquarius(11, "水瓶座", "01-20", "02-18"),
    Pisces(12, "双鱼座", "02-19", "03-20"),;
    
    /**
     * 序号
     */
    private int code;
    
    /**
     * 中文名称
     */
    private String nameCn;
    
    /**
     * 开始时间
     */
    private String startDate;
    
    /**
     * 结束时间
     */
    private String endDate;

    

    private ConstellationNameEnum(int code, String nameCn, String startDate, String endDate) {
        this.code = code;
        this.nameCn = nameCn;
        this.startDate = startDate;
        this.endDate = endDate;
    }
    
    /**
     * 根据日期查询星座名称枚举
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static ConstellationNameEnum getConstellationNameEnumByMonthDay(String monthDayStr){
        Objects.requireNonNull(monthDayStr, "monthDayStr");
        MonthDay monthDay = MonthDay.parse(MONTHDAY_FORMAT_PRE + monthDayStr);
        for(ConstellationNameEnum constellationNameEnum : ConstellationNameEnum.values()){
            MonthDay monthDayStart = MonthDay.parse(MONTHDAY_FORMAT_PRE + constellationNameEnum.getStartDate());
            MonthDay monthDayEnd = MonthDay.parse(MONTHDAY_FORMAT_PRE + constellationNameEnum.getEndDate());
            if (monthDay.equals(monthDayStart) || monthDay.equals(monthDayEnd)
                    || (monthDay.isAfter(monthDayStart) && monthDay.isBefore(monthDayEnd))) {
                return constellationNameEnum;
            }
        }
        return null;
    }

    /**
     * 根据日期查询星座中文名称
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static String getNameCnByMonthDay(String monthDayStr){
        ConstellationNameEnum constellationNameEnum = getConstellationNameEnumByMonthDay(monthDayStr);
        return constellationNameEnum != null ? constellationNameEnum.getNameCn() : null;
    }
    
    /**
     * 根据日期查询星座英文名称
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static String getNameEnByMonthDay(String monthDayStr){
        ConstellationNameEnum constellationNameEnum = getConstellationNameEnumByMonthDay(monthDayStr);
        return constellationNameEnum != null ? constellationNameEnum.name() : null;
    }
    

    public int getCode() {
        return code;
    }

    public String getNameCn() {
        return nameCn;
    }

    public String getStartDate() {
        return startDate;
    }

    public String getEndDate() {
        return endDate;
    }

}

主要的方法为:public static ConstellationNameEnum getConstellationNameEnumByMonthDay(String monthDayStr),通过对输入的月日字符串和枚举中的起始时间对比得出星座。

星座名称和时间范围来自百度百科

2. 应用

    /**
     * 根据日期查询星座中文名称
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static String getConstellationNameCn(String monthDayStr){
        return ConstellationNameEnum.getNameCnByMonthDay(monthDayStr);
    }
    
    /**
     * 根据日期查询星座中文名称
     * @param date
     * @return
     */
    public static String getConstellationNameCn(Date date){
        String monthDayStr = DateTimeFormatterUtil.format(date, DateTimeFormatterUtil.MM_DD_FMT);
        return ConstellationNameEnum.getNameCnByMonthDay(monthDayStr);
    }
    
    /**
     * 根据日期查询星座英文名称
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static String getConstellationNameEn(String monthDayStr){
        return ConstellationNameEnum.getNameEnByMonthDay(monthDayStr);
    }    

 

测试代码:

    /**
     * 星座计算测试
     */
    @Test
    public void constellationTest(){
        System.out.println(DateTimeCalculatorUtil.getConstellationNameCn("02-29"));
        System.out.println(DateTimeCalculatorUtil.getConstellationNameEn("02-29"));
        
        //2020-05-01 的星座
        System.out.println(DateTimeCalculatorUtil.getConstellationNameCn(DateTimeCalculatorUtil.getDate(2020, 5, 1)));
    }

 

输出:

双鱼座
Pisces
金牛座

 

 

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

 

Java日期时间API系列24—–Jdk8中java.time包中的新的日期时间API类,MonthDay类源码和应用,对比相同月日时间。

  Java8中为月日新增了类MonthDay,可以用来处理生日,节日、纪念日和星座等周期性问题。

1.MonthDay

  特别需要注意的:它的默认打印格式会带前缀”–” ,比如–12-03,同样的默认解析格式也需要加前缀。

1.1 部分源码

 

 * @implSpec
 * This class is immutable and thread-safe.
 *
 * @since 1.8
 */
public final class MonthDay
        implements TemporalAccessor, TemporalAdjuster, Comparable, Serializable {

    /**
     * Serialization version.
     */
    private static final long serialVersionUID = -939150713474957432L;
    /**
     * Parser.
     */
    private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
        .appendLiteral("--")
        .appendValue(MONTH_OF_YEAR, 2)
        .appendLiteral('-')
        .appendValue(DAY_OF_MONTH, 2)
        .toFormatter();

    /**
     * The month-of-year, not null.
     */
    private final int month;
    /**
     * The day-of-month.
     */
    private final int day;

通过源码可以看出使用final修饰MonthDay,MonthDay是线程安全类,同时实现了TemporalAccessor, TemporalAdjuster, Comparable, Serializable接口,有属性读取和设置等功能,但由于没有年部分,闰年2月29日的原因,没有加减功能。

 

 

 1.2 创建方式

     MonthDay monthDay1 = MonthDay.now();
        System.out.println(monthDay1);
        
        MonthDay monthDay2 = MonthDay.of(12, 3);
        System.out.println(monthDay2);

输出:

--02-29
--12-03

 

1.3 解析

System.out.println(MonthDay.parse("--12-03"));

 

2. 应用

对比相同月日和推算等

2.1 应用代码

    /**
     * 相同月日比较判断,用于生日,节日等周期性的日期比较判断。
     * @param localDate1
     * @param monthDay
     * @return
     */
    public static boolean isSameMonthDay(LocalDate localDate1, MonthDay monthDay){
        Objects.requireNonNull(localDate1, "localDate1");
        Objects.requireNonNull(monthDay, "monthDay");
        return MonthDay.of(localDate1.getMonthValue(), localDate1.getDayOfMonth()).equals(monthDay);
    }
    
    /**
     * 相同月日比较判断,用于生日,节日等周期性的日期比较判断。
     * @param localDate1
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static boolean isSameMonthDay(LocalDate localDate1, String monthDayStr){
        Objects.requireNonNull(monthDayStr, "monthDayStr");
        return isSameMonthDay(localDate1, MonthDay.parse(MONTHDAY_FORMAT_PRE + monthDayStr));
    }
    
    /**
     * 相同月日比较判断,用于生日,节日等周期性的日期比较判断。
     * @param localDate1
     * @param localDate2
     * @return
     */
    public static boolean isSameMonthDay(LocalDate localDate1, LocalDate localDate2){
        Objects.requireNonNull(localDate2, "localDate2");
        return isSameMonthDay(localDate1, MonthDay.of(localDate2.getMonthValue(), localDate2.getDayOfMonth()));
    }
    
    /**
     * 相同月日比较判断,用于生日,节日等周期性的日期比较判断。
     * @param date
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static boolean isSameMonthDay(Date date, String monthDayStr){
        return isSameMonthDay(DateTimeConverterUtil.toLocalDate(date), monthDayStr);
    }
    
    /**
     * 相同月日比较判断,用于生日,节日等周期性的日期比较判断。
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isSameMonthDay(Date date1, Date date2){
        Objects.requireNonNull(date1, "date1");
        Objects.requireNonNull(date2, "date2");
        return isSameMonthDay(DateTimeConverterUtil.toLocalDate(date1), DateTimeConverterUtil.toLocalDate(date2));
    }
    
    /**
     * 相同月日比较判断,与当前日期对比,用于生日,节日等周期性的日期比较判断
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static boolean isSameMonthDayOfNow(String monthDayStr){
        return isSameMonthDay(LocalDate.now(), monthDayStr);
    }
    
    /**
     * 下个固定月日相差天数,用于生日,节日等周期性的日期推算
     * @param localDate1
     * @param month
     * @param dayOfMonth
     * @return
     */
    public static long betweenNextSameMonthDay(LocalDate localDate1, int month, int dayOfMonth) {
        Objects.requireNonNull(localDate1, "localDate1");
        MonthDay monthDay1 = MonthDay.of(localDate1.getMonthValue(), localDate1.getDayOfMonth());
        MonthDay monthDay2 = MonthDay.of(month, dayOfMonth);
        
        // localDate1 月日 小于 month dayOfMonth
        if (monthDay1.compareTo(monthDay2) == -1) {
            return betweenTotalDays(localDate1.atStartOfDay(),
                    localDate1.withMonth(month).withDayOfMonth(dayOfMonth).atStartOfDay());
        } else {
            // 闰年2月29
            MonthDay leapMonthDay = MonthDay.of(2, 29);
            if (leapMonthDay.equals(monthDay2)) {
                LocalDate nextLeapYear = nextLeapYear(localDate1);
                return betweenTotalDays(localDate1.atStartOfDay(),
                        nextLeapYear.withMonth(month).withDayOfMonth(dayOfMonth).atStartOfDay());
            } else {
                LocalDate next = localDate1.plusYears(1);
                return betweenTotalDays(localDate1.atStartOfDay(),
                        next.withMonth(month).withDayOfMonth(dayOfMonth).atStartOfDay());
            }
        }
    }
    
    /**
     * 下个固定月日相差天数,用于生日,节日等周期性的日期推算
     * @param localDate
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static long betweenNextSameMonthDay(LocalDate localDate, String monthDayStr) {
        Objects.requireNonNull(monthDayStr, "monthDayStr");
        MonthDay monthDay2 = MonthDay.parse(MONTHDAY_FORMAT_PRE + monthDayStr);
        return betweenNextSameMonthDay(localDate, monthDay2.getMonthValue(), monthDay2.getDayOfMonth());
    }
    
    /**
     * 下个固定月日相差天数,用于生日,节日等周期性的日期推算
     * @param date
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static long betweenNextSameMonthDay(Date date, String monthDayStr) {
        Objects.requireNonNull(monthDayStr, "monthDayStr");
        MonthDay monthDay2 = MonthDay.parse(MONTHDAY_FORMAT_PRE + monthDayStr);
        return betweenNextSameMonthDay(DateTimeConverterUtil.toLocalDate(date), monthDay2.getMonthValue(),
                monthDay2.getDayOfMonth());
    }
    
    /**
     * 下个固定月日相差天数,与当前日期对比,用于生日,节日等周期性的日期推算
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static long betweenNextSameMonthDayOfNow(String monthDayStr) {
        Objects.requireNonNull(monthDayStr, "monthDayStr");
        MonthDay monthDay2 = MonthDay.parse(MONTHDAY_FORMAT_PRE + monthDayStr);
        return betweenNextSameMonthDay(LocalDate.now(), monthDay2.getMonthValue(),
                monthDay2.getDayOfMonth());
    }
    
    /**
     * 下个固定月日相差日期,用于生日,节日等周期性的日期推算
     * @param localDate
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static LocalDate nextSameMonthDay(LocalDate localDate, String monthDayStr){
        return localDate.plusDays(betweenNextSameMonthDay(localDate, monthDayStr));
    }
    
    /**
     * 下个固定月日相差日期,用于生日,节日等周期性的日期推算
     * @param date
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static Date nextSameMonthDay(Date date, String monthDayStr){
        return DateTimeConverterUtil.toDate(nextSameMonthDay(DateTimeConverterUtil.toLocalDate(date), monthDayStr));
    }
    
    /**
     * 下个固定月日相差日期,与当前日期对比,用于生日,节日等周期性的日期推算
     * @param monthDayStr MM-dd格式
     * @return
     */
    public static Date nextSameMonthDayOfNow(String monthDayStr){
        return nextSameMonthDay(new Date(), monthDayStr);
    }

 

2.2 测试代码

    /**
     * 相同月日对比
     */
    @Test
    public void sameMonthDayTest(){
        Date date = DateTimeCalculatorUtil.getDate(2020, 2, 29);
        System.out.println(date);
        
        //date的月日部分是否和02-29相等
        System.out.println(DateTimeCalculatorUtil.isSameMonthDay(date, "02-29"));
        //date的月日部分是否和new Date()的月日部分相等
        System.out.println(DateTimeCalculatorUtil.isSameMonthDay(date, new Date()));
        //当前时间月日部分是否和02-29相等
        System.out.println(DateTimeCalculatorUtil.isSameMonthDayOfNow("02-29"));
        
        //date的月日部分和下一个03-05相差天数
        System.out.println(DateTimeCalculatorUtil.betweenNextSameMonthDay(date, "03-05"));
        //当前时间月日部分和下一个03-05相差天数
        System.out.println(DateTimeCalculatorUtil.betweenNextSameMonthDayOfNow("03-05"));
        
        //date为准,下一个02-14的日期
        System.out.println(DateTimeCalculatorUtil.nextSameMonthDay(date, "02-14"));
        //date为准,下一个03-05的日期
        System.out.println(DateTimeCalculatorUtil.nextSameMonthDay(date, "03-05"));
        //date为准,下一个02-29的日期 ,02-29 只有闰年有。
        System.out.println(DateTimeCalculatorUtil.nextSameMonthDay(date, "02-29"));
        //当前时间为准,下一个02-29的日期  ,02-29 只有闰年有。
        System.out.println(DateTimeCalculatorUtil.nextSameMonthDayOfNow("02-29"));
    }

 

2.3 输出

Sat Feb 29 00:00:00 CST 2020
true
true
true
5
5
Sun Feb 14 00:00:00 CST 2021
Thu Mar 05 00:00:00 CST 2020
Thu Feb 29 00:00:00 CST 2024
Thu Feb 29 00:00:00 CST 2024

 

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