关于给定日期范围,生成相应的自然月区间

发布时间 2023-07-05 16:38:35作者: it-小林

前言

  前段时间,接到公司财务方的需求,原来的出账逻辑中,有一种商家是周结的出账周期,顾名思义,就是每个星期一的凌晨去跑上个星期的账单数据,给商家出账。但是,如果说,如果这个星期如果跨了月,那财务需要把这些账单进行拆分,有一定的工作量,因此想在出账的时候,就进行拆分,方便财务核对。

思路

   接到这个需求,思路无非就是,把这个出账的周期拆成两个账期,但是看了出账的逻辑,就是如果这个账期如果是没有数据,那这个账期就会跳过,不出帐,那这样的话,有一种极有有可能的情况是,这个时间区间跨了好几个月。按照产品经理的需求,那就把拆成每一个自然月。也就是说,2023-07-09  至 2023-09-20,要拆分成 2023-07-09至 2023-07-31,2023-08-01至2023-08-31,2023-09-01至2023-09-20。那开发的思路就不会很难理解,首先,我们要算出这个日期区间相隔多少个自然月,然后再把区间给求出来。

过程

 第一步,本来觉得这个应该不难,直接利用现有的工具。以下代码示例

    利用Java8新特性

String text1 = "2019-03-25";
Temporal startDate = LocalDate.parse(text1);
String text2 = "2022-05-30";
Temporal endDate = LocalDate.parse(text2);
long months = ChronoUnit.MONTHS.between(startDate, endDate);
System.out.println(months);

 这里有个坑,就是这个算出来的并不是我们要的自然月,而且只在一些特殊的日期会有问题,因此被我弃用了。

  后面又找了另一种,是引用Hutools的包

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.1.0</version>
</dependency>

 

Date startDateDay = new Date(1553443200000L);
Date endDateDay = new Date(System.currentTimeMillis());
long betweenMonth = DateUtil.betweenMonth(startDate, endDate, true);
System.out.println(betweenMonth);
        

 但是结果也是不尽人意,总是感觉不太符合我的期望。

后面又在网上找了其他的,基本上都没有找到合适的,索性就自己写。

以下是我自己写的,希望大家指出不足之处,谢谢!!

public static Integer getDiffMonths(Date beginDate, Date endDate){
    if(beginDate == null || endDate == null){
        return null;
    }
    if(beginDate.compareTo(endDate) >= 0){
        return null;
    }
    int beginYear = DateUtils.getYear(beginDate);
    int endYear = DateUtils.getYear(endDate);
    int beaginMonth = DateUtils.getMonth(beginDate);
    int endMonth = DateUtils.getMonth(endDate);
    //同一年
    if(beginYear == endYear){
        return endMonth - beaginMonth + 1;
    }else {
        return 12- beaginMonth + 1 + endMonth + (endYear-beginYear-1) * 12;
    }
}

  第二步,根据求出的月份数,算出区间

public static List<ShopTimeIntervalDTO> getTimeIntervalList(Date startDate, Date endDate){
    if(startDate == null || endDate == null){
        return null;
    }
    if(startDate.compareTo(endDate) >= 0){
       return null;
    }
    List<ShopTimeIntervalDTO> dataList = new ArrayList<>();
    Integer months = getDiffMonths(startDate, endDate);
    if(months == null || months <= 0){
        return dataList;
    }
    for(int i=0;i<months;i++){
        Date start = getBeginDayOfMonth(addMonths(startDate, i));
        Date end = getEndDayOfMonth(start);
        if(i == 0){
            start = startDate;
        }
        if(i == months-1){
            end = endDate;
        }
        ShopTimeIntervalDTO data = new ShopTimeIntervalDTO();
        data.setStartDate(start);
        data.setEndDate(end);
        dataList.add(data);
    }
    return dataList;
}

 其中 

public class ShopTimeIntervalDTO {

    /**
     * 开始时间
     */
    private Date startDate;

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    /**
     * 结束时间
     */
    private Date endDate;

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    @Override
    public String toString() {
        return "ShopTimeIntervalDTO{" +
                "startDate=" + startDate +
                ", endDate=" + endDate +
                '}';
    }
}

 

总结

  其实功能并不复杂,重点是要先自己整理好思路,网上工具只是做参考,适合自己的才是最好的,谢谢大家!!!!