package com.java110; import static org.junit.Assert.assertTrue; import com.java110.core.factory.PlutusFactory; import com.java110.dto.fee.FeeDto; import com.java110.dto.owner.OwnerCarDto; import com.java110.utils.util.DateUtil; import com.java110.utils.util.StringUtil; import org.bouncycastle.util.encoders.Base64; import org.junit.Test; import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Unit test for simple App. */ public class AppTest { /** * Rigorous Test :-) */ @Test public void should() { //解密 FeeDto feeDto = new FeeDto(); feeDto.setStartTime(DateUtil.getDateFromStringB("2023-01-01")); feeDto.setEndTime(DateUtil.getDateFromStringB("2023-01-12")); feeDto.setPrepaymentPeriod("20"); feeDto.setState(FeeDto.STATE_DOING); feeDto.setConfigEndTime(DateUtil.getDateFromStringB("2050-01-01")); feeDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE); feeDto.setPaymentCd("1200"); feeDto.setPaymentCycle("12"); getTargetEndDateAndOweMonth(feeDto,null); } public Map getTargetEndDateAndOweMonth(FeeDto feeDto, OwnerCarDto ownerCarDto) { Date targetEndDate = null; double oweMonth = 0.0; Map targetEndDateAndOweMonth = new HashMap<>(); //todo 判断当前费用是否已结束 if (FeeDto.STATE_FINISH.equals(feeDto.getState())) { targetEndDate = feeDto.getEndTime(); targetEndDateAndOweMonth.put("oweMonth", oweMonth); targetEndDateAndOweMonth.put("targetEndDate", targetEndDate); return targetEndDateAndOweMonth; } //todo 考虑费用项 费用提前生成 Calendar preEndTimeCal = Calendar.getInstance(); preEndTimeCal.setTime(feeDto.getEndTime()); if (StringUtil.isNumber(feeDto.getPrepaymentPeriod())) { preEndTimeCal.add(Calendar.DAY_OF_MONTH, Integer.parseInt(feeDto.getPrepaymentPeriod()) * -1); } Date preEndTime = preEndTimeCal.getTime(); //todo 当前费用为一次性费用 Date maxEndTime = feeDto.getConfigEndTime(); if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) { //先取 deadlineTime if (feeDto.getDeadlineTime() != null) { targetEndDate = feeDto.getDeadlineTime(); } else if (!StringUtil.isEmpty(feeDto.getCurDegrees())) { targetEndDate = feeDto.getCurReadingTime(); } else if (feeDto.getImportFeeEndTime() == null) { targetEndDate = maxEndTime; } else { targetEndDate = feeDto.getImportFeeEndTime(); } //判断当前费用是不是导入费用 oweMonth = 1.0; } else if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeDto.getFeeFlag())) { if (feeDto.getDeadlineTime() != null) { maxEndTime = feeDto.getDeadlineTime(); } Date billEndTime = DateUtil.getCurrentDate(); //建账时间 Date startDate = feeDto.getStartTime(); //计费起始时间 Date endDate = feeDto.getEndTime(); //缴费周期 long paymentCycle = Long.parseLong(feeDto.getPaymentCycle()); // 当前时间 - 开始时间 = 月份 double mulMonth = 0.0; mulMonth = dayCompare(startDate, billEndTime); // 月份/ 周期 = 轮数(向上取整) double round = 0.0; if ("1200".equals(feeDto.getPaymentCd())) { // 1200预付费 round = Math.floor(mulMonth / paymentCycle) + 1; } else { //2100后付费 round = Math.floor(mulMonth / paymentCycle); } // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间 targetEndDate = getTargetEndTime(round * paymentCycle, startDate);//目标结束时间 //todo 如果 到了 预付期 产生下个周期的费用 if (DateUtil.getFormatTimeStringB(targetEndDate).equals(DateUtil.getFormatTimeStringB(endDate)) && DateUtil.getCurrentDate().getTime() > preEndTime.getTime() ) { targetEndDate = getTargetEndTime((round + 1) * paymentCycle, startDate);//目标结束时间 } //todo 费用项的结束时间<缴费的结束时间 费用快结束了 取费用项的结束时间 if (maxEndTime.getTime() < targetEndDate.getTime()) { targetEndDate = maxEndTime; } //说明欠费 if (endDate.getTime() < targetEndDate.getTime()) { // 目标到期时间 - 到期时间 = 欠费月份 oweMonth = dayCompare(endDate, targetEndDate); } if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) { targetEndDate = feeDto.getEndTime(); } } else { // todo 周期性费用 //当前时间 Date billEndTime = DateUtil.getCurrentDate(); //建账时间 Date startDate = feeDto.getStartTime(); //计费起始时间 Date endDate = feeDto.getEndTime(); //缴费周期 long paymentCycle = Long.parseLong(feeDto.getPaymentCycle()); // 当前时间 - 开始时间 = 月份 double mulMonth = 0.0; mulMonth = dayCompare(endDate, billEndTime); // 月份/ 周期 = 轮数(向上取整) double round = 0.0; if ("1200".equals(feeDto.getPaymentCd())) { // 1200预付费 round = Math.floor(mulMonth / paymentCycle) + 1; } else { //2100后付费 round = Math.floor(mulMonth / paymentCycle); } // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间 targetEndDate = getTargetEndTime(round * paymentCycle, endDate);//目标结束时间 //todo 如果 到了 预付期 产生下个周期的费用 if (DateUtil.getFormatTimeStringB(targetEndDate).equals(DateUtil.getFormatTimeStringB(endDate)) && DateUtil.getCurrentDate().getTime() > preEndTime.getTime() ) { targetEndDate = getTargetEndTime((round + 1) * paymentCycle, startDate);//目标结束时间 } //费用项的结束时间<缴费的结束时间 费用快结束了 取费用项的结束时间 if (maxEndTime.getTime() < targetEndDate.getTime()) { targetEndDate = maxEndTime; } //说明欠费 if (endDate.getTime() < targetEndDate.getTime()) { // 目标到期时间 - 到期时间 = 欠费月份 oweMonth = dayCompare(endDate, targetEndDate); } if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) { targetEndDate = feeDto.getEndTime(); } } targetEndDateAndOweMonth.put("oweMonth", oweMonth); targetEndDateAndOweMonth.put("targetEndDate", targetEndDate); return targetEndDateAndOweMonth; } public Date getTargetEndTime(double month, Date startDate) { Calendar endDate = Calendar.getInstance(); endDate.setTime(startDate); Double intMonth = Math.floor(month); endDate.add(Calendar.MONTH, intMonth.intValue()); double doubleMonth = month - intMonth; if (doubleMonth <= 0) { return endDate.getTime(); } int futureDay = endDate.getActualMaximum(Calendar.DAY_OF_MONTH); Double hour = doubleMonth * futureDay * 24; endDate.add(Calendar.HOUR_OF_DAY, hour.intValue()); return endDate.getTime(); } public double dayCompare(Date fromDate, Date toDate) { double resMonth = 0.0; Calendar from = Calendar.getInstance(); from.setTime(fromDate); Calendar to = Calendar.getInstance(); to.setTime(toDate); //比较月份差 可能有整数 也会负数 int result = to.get(Calendar.MONTH) - from.get(Calendar.MONTH); //比较年差 int month = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12; //真实 相差月份 result = result + month; //开始时间 2021-06-01 2021-08-05 result = 2 2021-08-01 Calendar newFrom = Calendar.getInstance(); newFrom.setTime(fromDate); newFrom.add(Calendar.MONTH, result); //如果加月份后 大于了当前时间 默认加 月份 -1 情况 12-19 21-01-10 //这个是神的逻辑一定好好理解 if (newFrom.getTime().getTime() > toDate.getTime()) { newFrom.setTime(fromDate); result = result - 1; newFrom.add(Calendar.MONTH, result); } // t1 2021-08-01 t2 2021-08-05 long t1 = newFrom.getTime().getTime(); long t2 = to.getTime().getTime(); //相差毫秒 double days = (t2 - t1) * 1.00 / (24 * 60 * 60 * 1000); BigDecimal tmpDays = new BigDecimal(days); //相差天数 BigDecimal monthDay = null; Calendar newFromMaxDay = Calendar.getInstance(); newFromMaxDay.set(newFrom.get(Calendar.YEAR), newFrom.get(Calendar.MONTH), 1, 0, 0, 0); newFromMaxDay.add(Calendar.MONTH, 1); //下个月1号 //在当前月中 这块有问题 if (toDate.getTime() < newFromMaxDay.getTime().getTime()) { monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH)); return tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).doubleValue(); } // 上月天数 days = (newFromMaxDay.getTimeInMillis() - t1) * 1.00 / (24 * 60 * 60 * 1000); tmpDays = new BigDecimal(days); monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH)); BigDecimal preRresMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP); //下月天数 days = (t2 - newFromMaxDay.getTimeInMillis()) * 1.00 / (24 * 60 * 60 * 1000); tmpDays = new BigDecimal(days); monthDay = new BigDecimal(newFromMaxDay.getActualMaximum(Calendar.DAY_OF_MONTH)); resMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).add(preRresMonth).doubleValue(); return resMonth; } }