日期分割 groovy

/**
 * 合同日期处理
 * @AUTHOR: Lij
 * @Date: 2021-03-30 13:38
 * @DESCRIPTION:
 * @Version: 1.0
 */
class ContractDate {

    /**
     * key值表示付费周期, value表示周期包含的月份数
     */
    static final Map<Integer, Integer> CYCLE = [2:1, 3:3, 4:6, 5:12]

    /**
     * 按条件切割日期
     * @param start 开始日期
     * @param end 结束日期
     * @param type 结算类型 [1:按自然月结算, 2:按日期结算]
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return List<Map<String, Date>>
     */
    static def splitMonth(Date start, Date end, int type, int cycle){
        def monthArr = []
        // 按自然月, 非严格
        if(type == 0){
            monthArr = nature(start, end, cycle)
        }
        // 按自然月, 严格
        else if (type == 1){
            monthArr = natureStrict(start, end, cycle)
        }
        // 按日期
        else if(type == 2){
            monthArr = dayWay(start, end, cycle)
        }
        return monthArr
    }

    /**
     * 获取一个周期
     * @param date 日期
     * @param type 结算类型 [1:按自然月结算, 2:按日期结算]
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return Map<String, Date>
     */
    static Map<String, Date> getOneCycle(Date date, int type, int cycle){
        def monthMap = new HashMap<String, Date>()
        def startDate = date
        if(type == 0){
            startDate = addMonth(getBeginOfTheDayAfterThisDay(getMonthLastDay(date)), -CYCLE[cycle])
        }
        else if (type == 1){
            startDate = getCycleFirstDay(date, cycle)
        }
        else if(type == 2){
            startDate = getBeginOfThisDay(date)
        }
        def calcEndDate = addMonth(startDate, CYCLE[cycle])
        def endDate = getEndOfTheDayBeforeThisDay(calcEndDate)
        monthMap.startDate = startDate
        monthMap.endDate = endDate
        return monthMap
    }

    /**
     * 按日期 计算分期时段
     * <p>如按季度(cycle=3): </p>
     * <p>4月14日到7月13日为一个时间段,</p>
     * <p>7月14日到10月13日为下一个时间段,</p>
     * <p>以此类推.</p>
     * @param start 开始日期
     * @param end 结束日期
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return List<Map<String, Date>>
     */
    static def dayWay(Date start, Date end, int cycle){
        Date startDate = start
        List<Map<String, Date>> monthArr = []
        // 增量
        def c = CYCLE[cycle]
        while(startDate<=end){
            def midDate = getBeginOfThisDay(startDate)
            def midObj = [startDate: midDate]
            // 增加 c 后的日期
            def calcEndDate = addMonth(midDate, c)
            // 结束日期 需要取前一天的 23:59:59
            def endDate = getEndOfTheDayBeforeThisDay(calcEndDate)
            // 如果 周期的最后一天 超过(大于)截止日期 则终止循环
            if (endDate > end){
                break
            }
            midObj.endDate = endDate
            monthArr.push(midObj)
            // 下一个开始日期
            startDate = calcEndDate
        }
        if (startDate<=end){
            monthArr.push([startDate: startDate, endDate: end])
        }
        return monthArr
    }

    /**
     * 按自然周期(非严格)计算分期时段.
     * <p>如按季度(cycle=3):</p>
     * <p>4月14日到4月30日为一个时间段,</p>
     * <p>5月1日到7月31日为下一个时间段,</p>
     * <p>以此类推.</p>
     * @param start 开始日期
     * @param end 结束日期
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return List<Map<String, Date>>
     */
    static def nature(Date start, Date end, int cycle){
        Date startDate = start
        List<Map<String, Date>> monthArr = []
        def dayOfMonth = getDayOfMonth(start)
        def endDate = null
        // 不是 1 号
        if (dayOfMonth != 1){
            def calcStart = getBeginOfThisDay(start)
            def calcEnd = getMonthLastDay(start)
            // 结束日期 需要取当天的 23:59:59
            endDate = getEndOfThisDay(calcEnd)
            monthArr.push([startDate:calcStart, endDate:endDate>end?end:endDate])
            // 下一个开始日期
            startDate = getBeginOfTheDayAfterThisDay(calcEnd)
        }
        if (endDate && endDate<end){
            def list = dayWay(startDate, end, cycle)
            monthArr.addAll(list)
        }
        return monthArr
    }

    /**
     * 按自然周期(严格)计算分期时段.
     * <p>如按季度(cycle=3):</p>
     * <p>4月14日到6月30日为一个时间段,</p>
     * <p>7月1日到9月30日为下一个时间段,</p>
     * <p>以此类推.</p>
     * @param start 开始日期
     * @param end 结束日期
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     */
    static def natureStrict(Date start, Date end, int cycle){
        Date startDate = start
        List<Map<String, Date>> monthArr = []
        def cycleFirstDay = getCycleFirstDay(start, cycle)
        def endDate = null
        if (start > cycleFirstDay){
            def calcStart = getBeginOfThisDay(start)
            def calcEnd = getCycleLastDay(start, cycle)
            // 结束日期 23:59:59
            endDate = getEndOfThisDay(calcEnd)
            monthArr.push([startDate:calcStart, endDate:endDate>end?end:endDate])
            // 下一个开始日期
            startDate = getBeginOfTheDayAfterThisDay(calcEnd)
        }
        if (endDate && endDate<end){
            def list = dayWay(startDate, end, cycle)
            monthArr.addAll(list)
        }
        return monthArr
    }

    /**
     * 在 date 的基础上增加(减少) increment 天
     * @param date 日期
     * @param increment 增量
     */
    static def addDay(Date date, int increment){
        return add(date, increment, Calendar.DAY_OF_MONTH)
    }

    /**
     * 在 date 的基础上增加(减少) increment 月
     * @param date 日期
     * @param increment 增量
     */
    static def addMonth(Date date, int increment){
        return add(date, increment, Calendar.MONTH)
    }

    /**
     * 在 date 的基础上增加(减少) increment 数量的 type
     * @param date 日期
     * @param increment 增量
     * @param field 类型 如:Calendar.YEAR
     */
    static Date add(Date date, int increment, int field){
        def calendar = Calendar.getInstance()
        calendar.setTime(date)
        calendar.add(field, increment)
        return calendar.getTime()
    }

    /**
     * 获取当天 0 点 0 分 0 秒
     * @param date 日期
     * @return Date
     */
     static Date getBeginOfThisDay(Date date){
        Calendar c = Calendar.getInstance()
        c.setTime(date)
        c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH),0,0,0)
        c.set(Calendar.MILLISECOND,0)
        return c.getTime()
    }

    /**
     * 获取当天 23 点 59 分 59 秒
     * @param date 日期
     * @return Date
     */
    static Date getEndOfThisDay(Date date){
        Calendar c = Calendar.getInstance()
        c.setTime(date)
        c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH),23,59,59)
        c.set(Calendar.MILLISECOND,999)
        return c.getTime()
    }

    /**
     * 获取某个日期前一天的 23 点 59 分 59 秒
     * @param date 日期
     * @return Date
     */
    static Date getEndOfTheDayBeforeThisDay(Date date){
        def theDay = addDay(date, -1)
        def theEnd = getEndOfThisDay(theDay)
        return theEnd
    }

    /**
     * 获取某个日期后一天的 0 点 0 分 0 秒
     * @param date 日期
     * @return
     */
    static Date getBeginOfTheDayAfterThisDay(Date date){
        def theDay = addDay(date, 1)
        def theBegin = getBeginOfThisDay(theDay)
        return theBegin
    }

    /**
     * 获取当前日期中的日
     * @param date 日期
     * @return
     */
    static int getDayOfMonth(Date date){
        def c = Calendar.getInstance()
        c.setTime(date)
        return c.get(Calendar.DAY_OF_MONTH)
    }

    /**
     * 获取当前日期中的月
     * @param date 日期
     * @return
     */
    static int getMonth(Date date){
        def c = Calendar.getInstance()
        c.setTime(date)
        return c.get(Calendar.MONTH)
    }

    /**
     * 获取当前日期的年月日
     * @param date 日期
     * @return Map<String, Integer> yyyy:年, MM:月, dd:日
     */
    static Map<String, Integer> getYmd(Date date){
        def c = Calendar.getInstance()
        c.setTime(date)
        def res = [
                yyyy:c.get(Calendar.YEAR),
                MM:c.get(Calendar.MONTH),
                dd:c.get(Calendar.DAY_OF_MONTH)
        ]
        return res
    }

    /**
     * 获取 日期所在周期的最后一天的日期
     * @param date 日期
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return 日期, 0 点 0 分 0 秒
     */
    static Date getCycleLastDay(Date date, int cycle){
        def inc = CYCLE[cycle]
        def ymd = getYmd(date)
        def month = ymd.MM + 1
        def c = Calendar.getInstance()
        def lastMonth = (Math.ceil(month / inc) * inc) as Integer
        c.set(ymd.yyyy, lastMonth,0,0,0,0)
        c.set(Calendar.MILLISECOND, 0)
        return c.getTime()
    }

    /**
     * 获取 日期所在月的最后一天的日期
     * @param date 日期
     * @return 日期, 0 点 0 分 0 秒
     */
    static Date getMonthLastDay(Date date){
        def c = Calendar.getInstance()
        c.setTime(date)
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.getActualMaximum(Calendar.DAY_OF_MONTH),0,0,0)
        c.set(Calendar.MILLISECOND, 0)
        return c.getTime()
    }

    /**
     * 获取 日期所在周期的第一天的日期
     * @param date 日期
     * @param cycle 付费周期 [2:每月, 3:每季, 4:每半年, 5:每年]
     * @return 日期, 0 点 0 分 0 秒
     */
    static Date getCycleFirstDay(Date date, int cycle){
        def inc = CYCLE[cycle]
        def ymd = getYmd(date)
        def month = ymd.MM
        def c = Calendar.getInstance()
        def lastMonth = (Math.floor(month / inc) * inc) as Integer
        c.set(ymd.yyyy, lastMonth,1,0,0,0)
        c.set(Calendar.MILLISECOND, 0)
        return c.getTime()
    }

    /**
     * 获取 日期所在月的第一天的日期
     * @param date 日期
     * @return 日期, 0 点 0 分 0 秒
     */
    static Date getMonthFirstDay(Date date){
        def c = Calendar.getInstance()
        c.setTime(date)
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), 1,0,0,0)
        c.set(Calendar.MILLISECOND, 0)
        return c.getTime()
    }
    
    static void main(String[] args){
        def fmtStr = "yyyy-MM-dd HH:mm"
        def startDate = new Date(1550000000000L)
        def endDate = new Date(1600000000000L)
        println "${startDate.format(fmtStr)}\tTO\t${endDate.format(fmtStr)}"
        println "------------------------------------------------"
        def type = 0, cycle = 3
        def list = splitMonth(startDate, endDate, type, cycle)
        list.sort {a,b->a.startDate<=>b.startDate}
        
        list.each {
            println "${it.startDate.format(fmtStr)}\t\t${it.endDate.format(fmtStr)}"
        }
        println "------------------------------------------------"
        def one = getOneCycle(startDate, type, cycle)
        println "startDate:\t${one.startDate.format(fmtStr)}"
        println "endDate:  \t${one.endDate.format(fmtStr)}"
        println "------------------------------------------------"
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值