目录
- 前言
- 实现
- 1、获取当月的所有周
- 2、根据指定的第几周,获取这周的开始、结束时间
- 3、获取当前月某一周的所有日期
- 4、多个日期中,计算最大的连续天数
- 5、判断指定日期是否在某个范围内
前言
最近做项目,碰到一个比较复杂的日期查询方式,在这里记录一下,方便以后忘了随时能查到。
像我们一般查询日期,页面上用的日期选择器,一般都是直接查某一天或者选择开始、结束时间,查一个范围。不过这次需要我们按某月的某周来查询,比如页面上直接显示这个月有几周,然后选第一周就直接传第一周给后端。(如下面这种方式)
因此,我们要先计算这个月有几周,然后计算每周的起止时间,放到一个map中,通过前端传过来的第几周直接去map中拿。
实现
要计算起止时间,建议先引入hutool依赖,更方便。
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.11</version></dependency>
1、获取当月的所有周
第一步,我们要先获得这个月的所有周。这个不是按照每周七天算的,比如2023.1月,它的第一周是1号,最后一周是30、31号。像这种情况它不一定每周都有七天,这一周只有一天、两天也是算一周的。而不是直接按照这个月有多少天直接除以7天这么算的。
/** * 获取当前月的所有周 */public List<String> monthWeekNum(){ // DateUtil是hutool的类 DateTime end = DateUtil.endOfMonth(new Date()); // 获取本月最后一天 int weekNum = DateUtil.weekOfMonth(end); // 获取本月最后一天在第几周 List<String> list = new ArrayList<>(); for (int i = 1; i <= weekNum; i++) { list.add("第"+i+"周"); } return list;}
2、根据指定的第几周,获取这周的开始、结束时间
拿到了本月有几周,第二步就计算每周的开始、结束日期。
/** * 根据指定的第几周,获取这周的开始、结束时间 * @param week 第几周(比如第1周、第2周) */public static String[] getStartEndOfWeek(String week){ // 如果没有传week,则默认查询当前周的开始、结束时间 if (StrUtil.isEmpty(week)){ String[] result = new String[2]; Date date = new Date(); // 获取本周的开始时间和结束时间 result[0] = DateUtil.beginOfWeek(date).toString("yyyy-MM-dd"); result[1] = DateUtil.endOfWeek(date).toString("yyyy-MM-dd"); return result; } int weekNo = Integer.parseInt(week.replace("第", "").replace("周", "")); String weekOfDate = getWeekOfDate(weekNo); return weekOfDate.split(",");}/** * 指定周数,获取当前月本周的开始、结束时间 * @param weekNo 第几周 */public static String getWeekOfDate(int weekNo) { Date date = new Date(); DateTime start = DateUtil.beginOfMonth(date); // 获取本月的第一天 DateTime end = DateUtil.endOfMonth(date); // 获取本月最后一天 String weekOfDate = getWeekOfDate(start, end,weekNo); return weekOfDate;}/** * 指定时间计算有几周,并返回每周起止日期 * @param start 开始时间(本月第一天) * @param end 结束时间(本月最后一天) * @param weekNo 第几周 */public static String getWeekOfDate(Date start, Date end,int weekNo) { Map<Integer, String> weekOfDate = getWeekOfDate(start, end); return weekOfDate.get(weekNo);}/** * 指定时间计算有几周,并返回每周起止日期(这里也可以不用放到map中,直接返回某一周的起止时间就行) * @param start 开始时间 * @param end 结束时间 * @return week:第几周 start:每周开始时间 end:每周结束时间 */public static Map<Integer, String> getWeekOfDate(Date start, Date end) { Map<Integer, String> result = new HashMap<>(); StringBuffer sb = null; assert end != null; assert start != null; int weekNum = DateUtil.weekOfMonth(end); // 获取本月最后一天在第几周 System.out.println("指定日期所在月共有 "+weekNum+" 周"); Calendar cal = Calendar.getInstance(); // 设置一个星期的第一天,按中国的习惯一个星期的第一天是星期一 cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setTime(start); // 获得当前日期是一个星期的第几天 int dayWeek = cal.get(Calendar.DAY_OF_WEEK); if (1 == dayWeek) { cal.add(Calendar.DAY_OF_MONTH, -1); } for (int i = 1; i <= weekNum; i++) { sb = new StringBuffer(); if (i == 1) {//第一周以 start 开始 sb.append(DateUtil.format(start,"yyyy-MM-dd")); }else { sb.append(DateUtil.format(cal.getTime(),"yyyy-MM-dd")); } sb.append(","); if (i == weekNum) {//最后一周以 end 结束 sb.append(DateUtil.format(end,"yyyy-MM-dd")); }else { //设置这周的周日日期,1代表周日,取值范围1~7,设置1~7之外会从周日开始往前后推算,负前正后,DAY_OF_WEEK的日期变更范围只会是在当前日期的周 cal.set(Calendar.DAY_OF_WEEK,1); sb.append(DateUtil.format(cal.getTime(),"yyyy-MM-dd")); } result.put(i,sb.toString()); //调用 org.apache.commons.lang.time.DateUtils 包下的方法 //新增一天到下一周的开始日期 cal.setTime(DateUtils.addDays(cal.getTime(), 1)); } return result;}
这里参考文章:https://blog.csdn.net/qq_40579568/article/details/125547795
3、获取当前月某一周的所有日期
拿到某一周的起止时间后,我又需要获得这周的所有日期怎么办?
/** * 获取当前月某一周的所有日期 * @param week 第几周 */public static List<String> weekDay(String week){ String[] day = getStartEndOfWeek(week); String[] split1 = day[0].split("-"); String[] split2 = day[1].split("-"); int start = Integer.parseInt(split1[2]); int end = Integer.parseInt(split2[2]); int month = Integer.parseInt(split1[1]); List<String> list = new ArrayList<>(); for (int i = start; i <= end; i++) { list.add(month+"月"+i+"日"); } return list;}
4、多个日期中,计算最大的连续天数
除了上面获取每周起止日期外,还有个要求在多个日期中,计算最大的连续天数。
如:2023-01-01、2023-01-02、2023-01-10、2023-01-11、2023-01-12、2023-01-15 这几个日期中,最大的连续天数是3天。
/** * 多个日期中,计算最大的连续天数 * 例如: [1,2,3,5,7] 则判定为连续有3次 */public static int continuousDay(List<LocalDate> dateList){ if (dateList == null || dateList.size() ==0) { return 0; } dateList = dateList.stream().sorted(LocalDate::compareTo).collect(Collectors.toList()); int maxContinuousDay = 1; int continuousDay = 1; for (int i = 0; i < dateList.size(); i++) { if (i == dateList.size() -1){ break; } LocalDate date = dateList.get(i); LocalDate secondDate = dateList.get(i + 1); if (date.plusDays(1).equals(secondDate)){ continuousDay ++; }else { if (continuousDay > maxContinuousDay){ maxContinuousDay = continuousDay; } continuousDay = 1; } } return maxContinuousDay;}
参考文章:https://blog.csdn.net/UserFrank/article/details/125186332
5、判断指定日期是否在某个范围内
这里可以直接用hutool的 DateUtil 工具类判断。除了这些,DateUtil、 LocalDateTimeUtil 还有很多实用的方法,可以去看看 源码
// date 指定日期; start 范围开始时间; end 范围结束时间。boolean in = DateUtil.isIn(date, start, end);
目前用到的暂时就这些,以后可能会补充,有小伙伴想补充的欢迎留言。