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
通过源码可以看出使用final修饰MonthDay,MonthDay是线程安全类,同时实现了TemporalAccessor, TemporalAdjuster, Comparable
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