LocalDate:
-
如下需求:给出任意一天,给出当月第一天,最后一天,及当月多少天.
LocalDate localDate = LocalDate.now(); localDate = localDate.plus(2, ChronoUnit.DAYS); LocalDate firstDays = localDate.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDays = localDate.with(TemporalAdjusters.lastDayOfMonth()); int days = YearMonth.from(localDate).lengthOfMonth(); System.out.println(localDate + "->" + firstDays + "->" + lastDays + "->" + days);//需求完成 LocalDate date = YearMonth.from(localDate).atDay(13); System.out.println(date); //2017-09-17->2017-09-01->2017-09-30->30 //2017-09-13
分析上面得这个:两个关键点:
-
plus方法:
public LocalDate plus(long amountToAdd, TemporalUnit unit)
可以看出plus方法需要传入一个TemporalUnit类型得参数,那么为什么我们传入了ChronoUnit类型得呢?我们猜测ChronoUnit是TemporalUnit 的实现类,但是也解释不了为什么偏偏传这种?
public LocalDate plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { ChronoUnit f = (ChronoUnit) unit; switch (f) { case DAYS: return plusDays(amountToAdd); case WEEKS: return plusWeeks(amountToAdd); case MONTHS: return plusMonths(amountToAdd); case YEARS: return plusYears(amountToAdd); case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10)); case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100)); case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000)); case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd)); } throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); } return unit.addTo(this, amountToAdd); }
-
看它的全实现就明白了,原来它一上来直接判断的是不是ChronoUnit的实例,如果是才执行,如果不是则抛出不支持的异常!
-
第二个关键点: 我们怎么从LocalDate转换成YearMonth或者MonthDay呢?直接看方法是看不出来的,我们看下面这段代码:
public static YearMonth from(TemporalAccessor temporal) { if (temporal instanceof YearMonth) { return (YearMonth) temporal; } Objects.requireNonNull(temporal, "temporal"); try { if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) { temporal = LocalDate.from(temporal); } return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR)); } catch (DateTimeException ex) { throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " + temporal + " of type " + temporal.getClass().getName(), ex); } }
是的,要求传入的类型是TemporalAccessor接口,我们传入的LocalDate确是是它的子类,话不多说,我们分析下这个方法的执行.
-
先判断是不是YearMonth的实例,如果是直接转成结果返回.
-
检查参数不为空
-
判断是不是ISO类型的存取容器,如果不是,转换为LocalDate类型,然后取年和月构造出来,哈哈.我们觉得
YearMonth yearMonth=YearMonth.of(localDate.getYear(),localDate.getMonth());
比较难看的实现其实人家就是这么实现的.