java计算时间段内的一些特殊日期,及差值

java计算2个日期内的一些特殊日期,及差值

1.计算一个月后的时间,利用java8的LocalDate:

首先,Date转为LocalDate,

private static LocalDate getLocalDate(Date startDate) {
        Instant instant = startDate.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalDate();
    }

下两个月第一天:LocalDate date=LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth());

或者LocalDate.now().with((temporal) -> temporal.with(DAY_OF_MONTH, 1).plus(2, MONTHS));

当前日期添加一个月:LocalDate.now().with((temporal) -> temporal.plus(1, MONTHS));

明年第一天:LocalDate.now().with(TemporalAdjusters.firstDayOfNextYear());

 

2.计算日期时间段内开始时间,以及之后的每个时间段的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<String> listPlan = getDeliveryPlans(start, end,diffMonth);
        listPlan.forEach(System.out::println);

    }

    private static List<String> 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<String> 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<Integer, WeekData> weeks=weeks();
       for (Integer key:weeks.keySet()){
           System.out.println("每周开始时间及结束时间:"+weeks.get(key).toString());
       }
}
 public static Map<Integer, WeekData> weeks(){
        //开始时间为当前月开始时间
        LocalDate start = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        //结束时间为当前月结束时间
        LocalDate end = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());

        Map<Integer, WeekData> 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<LocalDate> 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())分组,并且每个星期以星期一开始

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dmlcq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值