Java的localdate如何调整一周起始日为周日
本来为了老外的习惯把周日定为一周的起始日,写着写着发现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)
,虽然
TemporalAdjusters.previous(DayOfWeek.SUNDAY)
最终返回的是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
TemporalField weekOfMonthTemporalField = WeekFields.SUNDAY_START.weekOfMonth();
weekOfMonthTemporalField
才是我们要找的,以周日为一周起点的更大范围下的周定义
有了它,我们就可以构造一个TemporalAdjuster
了,用于把参数日期按照weekOfMonthTemporalField
的定义调整到上一周
TemporalAdjuster temporalAdjuster = temporal -> temporal.minus(1, weekOfMonthTemporalField.getBaseUnit());
我们这里采用了Temporal
的minus
方法,减去一个1个weekOfMonthTemporalField
定义下的单位,因为之前我们提到了TemporalField
本来就是由TemporalUnit
组成的,所以这样操作是合理的
当然由于这里是时间单位,不是时间字段,所以不论是周一开始的周,还是周日开始的周,它们的单位都是周,而周在Java8的API中是有枚举的,也就是ChronoUnit
其中的WEEKS
,所以我们也可以这么写
TemporalAdjuster temporalAdjuster = temporal -> temporal.minus(1, ChronoUnit.WEEKS);
其实就是日期减了一周,然后减了一周之后,我们在按照要求把时间调整(with
方法,带TemporalField
参数的)到传入的DayOfWeek
即可,调整需要涉及时间字段,那我们就从刚才的周日开始的WeekFields
定义取出DayOfWeek
的定义,也就是
TemporalField dayOfWeekTemporalField = WeekFields.SUNDAY_START.dayOfWeek()
那这样,我们的TemporalAdjuster
就变为
TemporalAdjuster temporalAdjuster = temporal -> temporal.minus(1, ChronoUnit.WEEKS) .with(dayOfWeekTemporalField, 1);
为啥填入的是1,因为dayOfWeekTemporalField
是时间字段,是定义,在这个定义下,周日是第一天,所以这个with
方法含义就是按照dayOfWeekTemporalField
的定义修改该字段值为1
最后完整的代码:
LocalDate date = LocalDate.of(2020,10,21);TemporalField dayOfWeekTemporalField = WeekFields.SUNDAY_START.dayOfWeek();
TemporalAdjuster temporalAdjuster = temporal -> temporal.minus(1, WEEKS)
.with(dayOfWeekTemporalField, 1);
LocalDate newLocalDate = date.with(temporalAdjuster);
System.out.println(newLocalDate);
以上就是我的思路和答案,希望能对你有所帮助,拜了个拜(′▽`〃)
以上是 Java的localdate如何调整一周起始日为周日 的全部内容, 来源链接: utcz.com/a/62700.html