1.计算日期时间段内开始时间,以及之后的每个时间段的1号,可以是每3个月,也可以是每6个月,也可以是每年,直到结束日期。例子如下:
package test;
import utils.data.DateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoUnit.MONTHS;
/**
*
* @date 2020/8/12 18:09
*/
public class testDatePublic {
public static void main(String[] args) throws Exception {
String start="2020-01-03";
String end="2021-12-31";
int diffMonth=DeliveryPeriodEnum.TWELF_MONTH;
List listPlan = getDeliveryPlans(start, end,diffMonth);
listPlan.forEach(System.out::println);
}
private static List getDeliveryPlans(String start, String end,int diffMonth) throws Exception {
//转格式为java.util.Date
Date startDate = DateFormat.parseDate(start,DateFormat.DT_YYYY_MM_DD);
Date endDate = DateFormat.parseDate(end,DateFormat.DT_YYYY_MM_DD);
//java.util.Date date = new java.util.Date();
LocalDate startDate1 = getLocalDate(startDate);
System.out.println("开始时间:" + startDate1);
LocalDate endDate1 =getLocalDate(endDate);
System.out.println("结束时间:" + endDate1);
//得到相差月数
long monthDiff = ChronoUnit.MONTHS.between(startDate1, endDate1);
System.out.println("两个时间之间的月数差为:" + monthDiff);
List listPlan=new ArrayList<>();
LocalDate dateDeliver=startDate1;
for (int i = 0; i < monthDiff+1; i++) {
//下个日期
DeliveryPlan deliveryPlan = new DeliveryPlan();
//得到下个时间段第一天
LocalDate nextMonthBeginDate = getNextTimeLocalDate(dateDeliver,diffMonth);
//找到开始时间到下个月第一天
long daysDiff = ChronoUnit.DAYS.between(dateDeliver,nextMonthBeginDate);
System.out.println("两个时间之间的天数差为:" + daysDiff);
deliveryPlan.setInterestDays(Integer.valueOf(String.valueOf(daysDiff)));
//转换格式LocalDate=>Date
Date nextMonthDate = getDate(nextMonthBeginDate);
if(endDate.before(nextMonthDate)){
//如果结束时间小于下个月1号,则停止循环,最后一条数据日期为结束时间
listPlan.add(getJavaUtilDateToString(endDate));
break;
}else if(endDate.equals(nextMonthDate)){
//如果结束时间等于下个月1号,则停止循环
listPlan.add(getJavaUtilDateToString(nextMonthDate));
//得到下一个日期
dateDeliver=nextMonthBeginDate;
break;
}else{
//没到结束时间继续循环
//记录下个时间段开始时间
listPlan.add(getJavaUtilDateToString(nextMonthDate));
//得到下一个日期
//赋值下个时间段开始时间
dateDeliver=nextMonthBeginDate;
}
}
return listPlan;
}
private static LocalDate getNextTimeLocalDate(LocalDate dateDeliver,int diffMonth) {
switch (diffMonth) {
case 1:
dateDeliver = dateDeliver.with(TemporalAdjusters.firstDayOfNextMonth());
break;
case 3:
dateDeliver = dateDeliver.with((temporal) -> temporal.with(DAY_OF_MONTH, 1).plus(3, MONTHS));
break;
case 6:
dateDeliver = dateDeliver.with((temporal) -> temporal.with(DAY_OF_MONTH, 1).plus(6, MONTHS));
break;
case 12:
dateDeliver = dateDeliver.with(TemporalAdjusters.firstDayOfNextYear());
//dateDeliver = dateDeliver.with((temporal) -> temporal.with(DAY_OF_YEAR, 1).plus(1, YEARS));
break;
}
return dateDeliver;
}
/**
*@Description Date转LocalDate
*@Date 2020/8/6
*/
private static LocalDate getLocalDate(Date startDate) {
Instant instant = startDate.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
return localDateTime.toLocalDate();
}
/**
*@Description Date转String
*@Date 2020/8/17
*/
private static String getJavaUtilDateToString(java.util.Date date){ // java.util.Date 转 String
Instant instant = date.toInstant();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String dateString = localDateTime.format(formatter);
return dateString;
}
/**
*@Description LocalDate转Date
*@Date 2020/8/6
*/
private static Date getDate(LocalDate beginDate) {
ZoneId zoneId = ZoneId.systemDefault();
Instant instant = beginDate.atStartOfDay().atZone(zoneId).toInstant();
return Date.from(instant);
}
}
class DeliveryPeriodEnum {
public static final int ONE_MONTH = 1;//一个月
public static final int THREE_MONTH = 3;//三个月
public static final int SIX_MONTH = 6;//六个月
public static final int TWELF_MONTH = 12;//12个月
}
打印结果:
开始时间:2020-01-03
结束时间:2021-12-31
两个时间之间的月数差为:23
两个时间之间的天数差为:180
两个时间之间的天数差为:184
两个时间之间的天数差为:181
两个时间之间的天数差为:184
2020-07-01
2021-01-01
2021-07-01
2021-12-31
这里转换方法就不赘述了,重点说下主要是利用了java8的ChronoUnit的between()方法、LocalDate.with()方法
TemporalAdjusters.firstDayOfNextMonth()方法及其源代码。
ChronoUnit的between()方法:计算2个时间相隔天数。源码一看就知道原理。
LocalDate.with()方法:配合TemporalAdjusters使用的方法
TemporalAdjusters:相当于一个常量,里面提供了一些常用的查询时间的接口
使用{@code TemporalAdjuster}有两种等效的方法。
第一种方法是直接调用接口上的方法。
第二种方法是使用{@link Temporal#with(TemporalAdjuster)}
比方说firstDayofYear(),利用with(ChronoField chronoField,long newValue).plus(long amountToAdd, TemporalUnit unit)方法可以实现参数加减。都是基于LocalDate这个类的方法重写。
2.获得一个月的每周开始时间及结束时间(转载)
public static void main(String[] args) throws Exception {
Map weeks=weeks();
for (Integer key:weeks.keySet()){
System.out.println("每周开始时间及结束时间:"+weeks.get(key).toString());
}
}
public static Map weeks(){
//开始时间为当前月开始时间
LocalDate start = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
//结束时间为当前月结束时间
LocalDate end = LocalDate.now().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;
}
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;
}
}
这个使用Stream.iterate(start, localDate -> localDate.plusDays(1l))获得开始时间加一天的所有集合,用limit(ChronoUnit.DAYS.between(start, end)+1)限制只能为到结束时间,用Collectors.groupingBy(localDate -> localDate.get(WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth())分组,并且每个星期以星期一开始