本来为了老外的习惯把周日定为一周的起始日,写着写着发现LocalDate计算时是把周一当作起始日的
没出过国全凭小学讲的周日是起始日
如下是计算2020-10-21上一周的周日
本来以为值应该是2020-10-11
但实际输出的值是2020-10-18
LocalDate date = LocaDate.of(2020,10,21);
date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY));
这个Localdate有哪个接口能快速调整吗,哭了
外国的文化习惯和外国的代码设计其实还是有很大差别的,毕竟代码是全球的人都要用的,是不能强行说偏袒某一方的(不像现在的漂亮国,扯远了),只能说代码里唯一借鉴了外国的只是用字母而已,其实代码设计是一个逻辑思考过程,题主太焦急了一点,不妨,我们慢慢来看
首先是
TemporalAdjusters.previous
方法,在该方法的注释中已经提到了,该方法采用的时间字段是ChronoField.DAY_OF_WEEK
,也就是按照一周7天来算,也就是满打满算的一周七天,并且返回上一次出现的你传入的DayOfWeek
注意这里说的是上一次的,而不是上一周的
有区别么?当然有,举个例子,还是用你的
LocaDate.of(2020,10,21)
,虽然最终返回的是
2020-10-18
,那如果填入的是DayOfWeek.MONDAY
,也就是上一个周一,会是多少呢?难道会是2020-10-12
日么?也就是上一周周一。不是的,答案其实是2020-10-19
,也就是上一个周一,不是上一周的周一所以首先在方法选型上,可能就不太对口,更不用谈是不是周一开始一周还是周日开始一周了,用这个方法是完成不了根据一个时间取到上一周的某个星期的问题
(如果不想看下面的思路,可能写的有点绕,容易混乱,可以直接拖到最下面查看最终代码)
当然也不是说
TemporalAdjusters.previous
方法完全没用,起码在注释中已经说到,这样的处理适用于很多日历系统,算是比较通用的方法吧不说
TemporalAdjusters.previous
了,咱们来看看题主要解决的问题如何操作。我觉得关键就是在于上一个和上一周的区别
DayOfWeek
的,比DayOfWeek
更大范围,在更大范围的定位里,找到上一周,然后再回到上一周中,根据DayOfWeek
定义里需要修改的数值进行修改。当然你也可以先修改DayOfWeek
定义里需要的数值,然后再找到上一周。顺序肯定是可以颠倒的所以说从理解上来说是有2步要做的。如果是对Java8时间API设计比较了解的话,应该知道,在
API
设计中描述飘渺的时间,主要就是靠定义,也就是时间字段的定义,一个时间,用不同的时间字段去描述,是可以获取到不同的值,这也就是时间字段+数值=时间在时间顶层接口
TemporalAccessor
的get
方法就可以见一斑那时间字段
TemporalField
由于它是定义,所以时间定义上肯定会有单位,也就是TemporalUnit
,以及范围,比如一个分钟有60秒,一周有7天,一年有365天等等,这都是基于某个单位下的数值范围。所以我们现在需要的就是构造一个周定义,单位肯定是天,范围也是7天,但是最小一周也有1天,不像之前提到的的
ChronoField.DAY_OF_WEEK
,它的最小一周也有7天,因为是满打满算嘛那这个定义我在另一个回答里有提到就是参考
WeekFields
的静态变量SUNDAY_START
WeekFields
可以简单理解为构建自定义一周的工具类,里面有个静态变量SUNDAY_START
就是以周日为起点,最小一周只有1天的WeekFields
定义了此时还不是周定义,因为周定义需要在月份中,而恰好
WeekFields
提供了方法weekOfMonth
weekOfMonthTemporalField
才是我们要找的,以周日为一周起点的更大范围下的周定义有了它,我们就可以构造一个
TemporalAdjuster
了,用于把参数日期按照weekOfMonthTemporalField
的定义调整到上一周我们这里采用了
Temporal
的minus
方法,减去一个1个weekOfMonthTemporalField
定义下的单位,因为之前我们提到了TemporalField
本来就是由TemporalUnit
组成的,所以这样操作是合理的当然由于这里是时间单位,不是时间字段,所以不论是周一开始的周,还是周日开始的周,它们的单位都是周,而周在Java8的API中是有枚举的,也就是
ChronoUnit
其中的WEEKS
,所以我们也可以这么写其实就是日期减了一周,然后减了一周之后,我们在按照要求把时间调整(
with
方法,带TemporalField
参数的)到传入的DayOfWeek
即可,调整需要涉及时间字段,那我们就从刚才的周日开始的WeekFields
定义取出DayOfWeek
的定义,也就是那这样,我们的
TemporalAdjuster
就变为为啥填入的是1,因为
dayOfWeekTemporalField
是时间字段,是定义,在这个定义下,周日是第一天,所以这个with
方法含义就是按照dayOfWeekTemporalField
的定义修改该字段值为1整合一下完整的代码:
你也可以自己模仿
TemporalAdjusters
创建一个属于自己的TemporalAdjuster
工厂CustomTemporalAdjusters
然后调用起来就比较方便了
但是这样做
CustomTemporalAdjusters
中的处理还是有点局限性,万一想看上一周的周三,周四呢?现在只能处理周日,所以我们再稍微改一下就可以了,主要修改最后的调整方法,也就是with(WeekFields.SUNDAY_START.dayOfWeek(), 1);
,这里为什么是1,是因为在WeekFields.SUNDAY_START.dayOfWeek()
的定义下是1,也就是DayOfWeek.SUNDAY
在WeekFields.SUNDAY_START.dayOfWeek()
定义为1,所以我们只要把需要查看的DayOfWeek
放到WeekFields.SUNDAY_START.dayOfWeek()
的定义里获取值即可,这个值就是需要修改的。也就是用到我们TemporalAccessor
的get
方法最终代码应该是这样的
调用的时候,两种方法都可以
以上就是我的思路和答案,希望能对你有所帮助,拜了个拜(′▽`〃)