java 获取近五月的日期_java 获取某个月的每周的开始日期和结束日期

题主,以下是我的思考思路,仅供参考:

读完需求,感觉输入输出大体是这个样子,

输入:yyyy-MM年月日期一个

输出:返回该年月所在月的所有周信息(每周的起始日期和结束日期)

既然是通过某一个月找到该月每周的起始日期、结束日期,那换句话说,一个月里有很多日期,这么日期它可以按照周来分类,第一周的日期为一类,第二周的日期为一类,以此类推,然后每一类中按照日期升序排序,我取第一个日期和最后一个日期最终就可以达到题主要求了,至此除了输入输出外,中间过程应该是这个样子

输入:yyyy-MM年月日期一个

yyyy-MM转化为List

List按照周进行分类得到类似一个map的结果Map>(其中key就是第几周)

Map>中每一个List取第一个值得到该周的第一天,取最后一个值得到该周的最后一天

输出:返回该年月所在月的所有周信息(每周的起始日期和结束日期)

有了以上一个步骤,我们再来一一解决步骤需要用到的代码,当然我这里没有选择用 java calender 类,emmm,我觉得它们实在太臃肿了,也容易犯错,API也不太好用,就以Java8的新时间API来替代了

在Java8的新时间API中,以前表示一个时间的庞大齐全的Date类被拆分了成了很多类(以前一个Date对象既表现了日期,也表现了时间,也表现了时区,大而全但不好用),这里我们要用到的是仅表示日期的YearMonth(yyyy-MM)和LocalDate(yyyy-MM-dd),YearMonth就表达一个年月,LocalDate就表达一个年月日

所以上诉需求立马转换为

输入:YearMonth年月日期一个

YearMonth转化为List

List按照周进行分类得到类似一个map的结果Map>(其中key就是第几周可以)

Map>中每一个List取第一个值得到该周的第一天,取最后一个值得到该周的最后一天

输出:返回该年月所在月的所有周信息(每周的起始日期和结束日期)

由于最终我们是在List中取第一个日期和最后一个日期作为最终返回结果,因此套用那句我不知道在哪里看到的话:引用新的编程元素,可以增加代码的可读性,所以我们加一个新的类型WeekData来表示这么一个返回结果

static class WeekData{

// 一周的开始时间

private LocalDate start;

// 一周的结束时间

private LocalDate end;

public WeekData(List localDates) {

this.start = localDates.get(0);

this.end = localDates.get(localDates.size()-1);

}

@Override

public String toString() {

return "开始时间:" + this.start + ",结束时间:" + this.end;

}

}

所以上诉需求立马转换为

输入:YearMonth年月日期一个

YearMonth转化为List

List按照周进行分类得到类似一个map的结果Map(其中key就是第几周可以)

输出:返回该年月所在月的所有周信息(每周的起始日期和结束日期)

现在就可以来解决每个步骤代码了,这样一个转换的方法,初始状态肯定是这样YearMonth作为传参,返回一个Map

private static Map weeks(YearMonth yearMonth){

// TODO

}

第一个步骤,YearMonth转化为List,表示的是这个月的所有日期,这种List的,我第一想法就是用Java8的stream,首先根据yearMonth获得这个月的开始日期和结束日期,用LocalDate的with方法即可,with就是调整的意思,想啥调整就咋调整非常灵活,随便取一个日期(我这里取的是但当前日期)

private static Map weeks(YearMonth yearMonth){

LocalDate start = LocalDate.now().with(yearMonth).with(TemporalAdjusters.firstDayOfMonth());

LocalDate end = LocalDate.now().with(yearMonth).with(TemporalAdjusters.lastDayOfMonth());

}

完成。。。是很简单吧,还有封装好的TemporalAdjusters.firstDayOfMonth()和TemporalAdjusters.lastDayOfMonth()

接下来我们来构造stream,用Stream.iterate(start, localDate -> localDate.plusDays(1l))构造一个无限流,它代表,以start作为起始值,按照第二个参数localDate -> localDate.plusDays(1l)也就是加一天的方式构造一个无限流,当然我要的不是无限,而是要到这个月末,所以limit(ChronoUnit.DAYS.between(start, end) + 1),这样就把这个无限流截断了

private static Map weeks(YearMonth yearMonth){

LocalDate start = LocalDate.now().with(yearMonth).with(TemporalAdjusters.firstDayOfMonth());

LocalDate end = LocalDate.now().with(yearMonth).with(TemporalAdjusters.lastDayOfMonth());

List localDates = Stream.iterate(start, localDate -> localDate.plusDays(1l))

.limit(ChronoUnit.DAYS.between(start, end) + 1)

.collect(Collectors.toList());

}

这样第一步就完成了,第二步,按周分类,这里有一个知识点,给一个LocalDate对象,怎么判断它是该月的第几周,这里肯定要用LocalDate的get方法,因为这个方法就是表示从当前日期中获取某个属性值,参数是接口TemporalField,你需要传入一个实现类即可,这个实现类就是定义了这个属性,当然JDK默认有一个实现类枚举ChronoField,里面有很多好用的实现类可以用,所以很容易就会选到一个枚举ChronoField.ALIGNED_WEEK_OF_MONTH,看起来好像是对的,ALIGNED不认识,WEEK_OF_MONTH感觉意思很明白,貌似能用,其实不然,这个实现类定义的一周跟我们想象中的不一样,它的一周是按照完整7天来算的,拿8月6号来看,我们感觉是第二周,但是实际结果是第一周,因为要满打满算的7天才算一周,8月6号还是算第一周的第六天而已

e0cbf910fe5ef4afb9d9945623357e25.png

所以得换个方法,ChronoField.ALIGNED_WEEK_OF_MONTH是按照周的一共7天这个维度来定义周,但是跟我们想要的周定义不太一样,我们定义的周,例如8月,前面的5天就应该是第一周了,也就是说,我们想象的周,不是说几天是一周,应该是周一是一周的开始,周日是一周的结束,就算只有一个周日,那也是一周,所以我们就看到另一个类WeekFields其中的静态变量SUNDAY_START

c4fcc90c82d75daf5f4996182d9a645a.png

从注释来看是我们要的,不过是以星期天为一周开始的(这是国外的默认了,国内还是以周一为第一周开始的),所以我们直接用它的方式来构造一个就可以啦

localDate.get(WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth()

最后完整的就是

private static Map weeks(YearMonth yearMonth){

LocalDate start = LocalDate.now().with(yearMonth).with(TemporalAdjusters.firstDayOfMonth());

LocalDate end = LocalDate.now().with(yearMonth).with(TemporalAdjusters.lastDayOfMonth());

Map map = Stream.iterate(start, localDate -> localDate.plusDays(1l))

.limit(ChronoUnit.DAYS.between(start, end)+1)

.collect(Collectors.groupingBy(localDate -> localDate.get(WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth()),

Collectors.collectingAndThen(Collectors.toList(), WeekData::new)));

return map;

}

最后用了哈Collectors.groupingBy和Collectors.collectingAndThen配合了下,总之还算是比较简洁的写法,希望能帮到你

最后简单打印哈获得map,看看结果

92836a081bf88abdcf7d4ead4c2ed8b4.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值