本次开发场景如下:
用户的计划是排在周三的,但是用户的前端需要显示在周五上,所以理论上来讲,我只需获取用户周三是否有计划,如果有计划,则在查询中使用,DATE_ADD(日期, INTERVAL 2 DAY)函数返回周三的日期加上两天即可,但是事实上并没有那么简单,这里还需要考虑跨月的问题。
例如2023-03-01是周五 则我需要查询2023-02-28周三是否有审核计划,而且我返回给前端的数据是截取出来的,例如2023-03-01,我在SQL中会截取到只剩下01这个天数返回给前端,2023-03是不会返回给前端的,这就造就了一个问题,例如我查询2月份的计划,那么2月28日是周三有审核计划,他就会加到2023-03-01并且截取01返回给我,但是我前端显示的是每月份的,所以如果返回给我01,那他默认会是在2月01这天,这天显然是周四,不符合我的逻辑,所以需要解决月初和月末的问题。
综上所述的两个跨月问题就是:
如果本月第一天是周四或者周五,则获取上个月最后一个周三的日期(具体的逻辑可以自己好好想想,看看日历这个容易理解)
如果本月最后一个周三加上两天之后大于本月最后一天,则不需要获取本月最后一个周三的日期
我们先来看最简单的代码,不考虑跨月的问题,例如:在2024年3月,获取3月中每个周三的日期(PS:代码中大量运用到了LocalDate类如果不熟练请看我这篇文章)
详解LocalDatehttps://blog.csdn.net/jialuosi/article/details/133770363?spm=1001.2014.3001.5501
public static void main(String[] args) {
//假定我需要获取2024年03月的,本周三的所有日期
int year = 2024;
int month = 03;
//使用LocalData来获取本月的第一天
LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
//使用LocalData来获取本月的最后一天
//日期.lengthOfMonth() : 获取日期所在月份的天数:
LocalDate lastDayOfMonth = LocalDate.of(year, month, firstDayOfMonth.lengthOfMonth());
//创建存放星期三日期的List
List<LocalDate> wednesdayDates = new ArrayList<>();
//临时变量 当天
LocalDate currentDay = firstDayOfMonth;
//如果 当天的日期小于本月最后一天 或者 当天等于本月最后一天 则执行循环
while (currentDay.isBefore(lastDayOfMonth) || currentDay.isEqual(lastDayOfMonth)) {
//日期.getDayOfWeek() : 获取星期几枚举值 返回值为DayOfWeek类型
//DayOfWeek.WEDNESDAY : 星期三的枚举值
if (currentDay.getDayOfWeek() == DayOfWeek.WEDNESDAY) {
//如果当天的值为星期三 则添加到List中
wednesdayDates.add(currentDay);
}
// 当天天数加一 重新开始循环
currentDay = currentDay.plusDays(1);
}
System.out.println(wednesdayDates);
}
输出的List结果为:
[2024-03-06, 2024-03-13, 2024-03-20, 2024-03-27]
上面的代码非常简单,接下来我们看看考虑跨月的问题,先来看总代码,我把它抽成了一个函数,然后我们挨个解析
public static LocalDate[] getWednesdayDates(int year, int month) {
LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
LocalDate lastDayOfMonth = LocalDate.of(year, month, firstDayOfMonth.lengthOfMonth());
List<LocalDate> wednesdayDates = new ArrayList<>();
// 检查本月第一天是周四或周五
if (firstDayOfMonth.getDayOfWeek() == DayOfWeek.THURSDAY || firstDayOfMonth.getDayOfWeek() == DayOfWeek.FRIDAY) {
// 获取上个月最后一个周三的日期
LocalDate lastWednesdayOfPreviousMonth = firstDayOfMonth.minusDays(1).with(DayOfWeek.WEDNESDAY);
wednesdayDates.add(lastWednesdayOfPreviousMonth);
}
// 循环遍历本月的每一天,找到所有周三日期
LocalDate currentDay = firstDayOfMonth;
while (currentDay.isBefore(lastDayOfMonth) || currentDay.isEqual(lastDayOfMonth)) {
if (currentDay.getDayOfWeek() == DayOfWeek.WEDNESDAY) {
wednesdayDates.add(currentDay);
}
currentDay = currentDay.plusDays(1);
}
// 检查本月最后一个周三加两天后是否超过了本月最后一天
LocalDate lastWednesdayOfMonth = lastDayOfMonth.with(DayOfWeek.WEDNESDAY);
if (lastWednesdayOfMonth.plusDays(2).isAfter(lastDayOfMonth)) {
wednesdayDates.remove(lastWednesdayOfMonth);
}
// 将List转换为数组
LocalDate[] wednesdayArray = new LocalDate[wednesdayDates.size()];
wednesdayArray = wednesdayDates.toArray(wednesdayArray);
return wednesdayArray;
}
首先我们先解决月初的跨月问题:如果本月第一天是周四或者周五,则获取上个月最后一个周三的日期
if (firstDayOfMonth.getDayOfWeek() == DayOfWeek.THURSDAY || firstDayOfMonth.getDayOfWeek() == DayOfWeek.FRIDAY) {
// 获取上个月最后一个周三的日期
// firstDayOfMonth.minusDays(1):firstDayOfMonth是本月第一天 minusDays(1)是减去一天,则这个日期获取到的就是上个月的最后一天
// with() 方法用于返回一个新的日期时间对象,with(DayOfWeek.WEDNESDAY)方法将日期调整为 当前日期所在周的周三 。
// with(DayOfWeek.WEDNESDAY) :这个方法会找到与指定星期几(这里是周三)最接近的日期
LocalDate lastWednesdayOfPreviousMonth = firstDayOfMonth.minusDays(1).with(DayOfWeek.WEDNESDAY);
wednesdayDates.add(lastWednesdayOfPreviousMonth);
}
这个代码的主要就是 日期.with(DayOfWeek.WEDNESDAY) 这个方法,同样的,看月末
LocalDate lastWednesdayOfMonth = lastDayOfMonth.with(DayOfWeek.WEDNESDAY);
// 最后一天所在周的周三日期 加上两天后 如果大于最后一天 则在数组中去掉这个周三的日期
if (lastWednesdayOfMonth.plusDays(2).isAfter(lastDayOfMonth)) {
wednesdayDates.remove(lastWednesdayOfMonth);
}
问题到这里差不多就解决了,我们来看看输出:
2024-02月是一个很好的例子,他的第一天是周五,所以要返回上个月最后一个周三的日期
而月末最后一个周三2024-02-28加两天正好跨月到了2024-03-01,所以28日也不应该输出
问题到这里就解决的差不多了,希望能有所收获