Java日期时间API系列24

Wesley13
• 阅读 544

  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日的原因,没有加减功能。

Java日期时间API系列24

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
Java日期时间API系列30
  实际使用中,经常需要使用不同精确度的Date,比如保留到天2020042300:00:00,保留到小时,保留到分钟,保留到秒等,常见的方法是通过格式化到指定精确度(比如:yyyyMMdd),然后再解析为Date。Java8中可以用更多的方法来实现这个需求,下面使用三种方法:使用Format方法、 使用Of方法和使用With方法,性能对比,使用
Wesley13 Wesley13
3年前
Java日期时间API系列26
Java8中为年月新增了类YearMonth,可以用来表示卡片过期时间等问题。1.YearMonth默认格式为:2007121.1部分源码\\@implSpec\Thisclassisimmutableandthreadsafe.\\@since1.8