记录:根据开始日期和结束日期计算车位月卡费用

271 阅读3分钟

计算规则

费用 = 数量 * 单价。数量根据开始日期和结束日期计算,例如日期区间为2021-09-05~2021-12-08,9月5日-10月4日这种为一个月,不足一个月则数量 = 天数 / 自然月天数,则数量 = 3 + 4 / 31

由于每个月天数不一样,2月又比较特殊,可能出现的情况比较多,下表列出所有可能的情况,并列出计算规则

开始日期结束日期数量计算规则备注
2021-11-102021-12-091
2021-11-102021-12-08(30 - 10 + 1) / 30 + 8 / 31
2021-11-102021-11-30(30 - 10 + 1) / 30
2021-11-102021-12-121 + (12 - 9) / 31
2021-11-102022-01-092
2021-11-102022-01-081 + (31 - 10 + 1) / 31 + 8 / 31(31 - 10 + 1) / 31指12月份
2021-11-102022-02-082 + (31 - 10 + 1) / 31 + 8 / 28(31 - 10 + 1) / 31指1月份
2021-11-102022-03-083 + (28 - 10 + 1) / 28 + 8 / 31(28 - 10 + 1) / 28指2月份
2021-11-102022-01-122 + (12 - 9) / 31
2021-11-102022-02-123 + (12 - 9) / 28
2021-01-312021-02-2711月28、29、30、31 加1个月减去1天后,都等于2月27日
2021-01-302021-02-271
2021-01-292021-02-271
2021-01-282021-02-271
2021-01-312021-02-281 + (28 - 27) / 28
2021-01-302021-02-281 + (28 - 27) / 28
2021-01-292021-02-281 + (28 - 27) / 28
2021-01-282021-02-281 + (28 - 27) / 28
2021-01-272021-02-281 + (28 - 26) / 28
2021-02-012021-02-281

代码实现

import moment from 'moment';

export default {
  methods: {
    /**
     * 11.5-12.4为一个月
     */
    calcAmountAndSum(startTime, endTime) {
      let amount = '';
      let momentStart = moment(startTime), momentEnd = moment(endTime);
      // 开始、结束年、月、日、月天数
      let startYear = momentStart.year(), startMonth = momentStart.month(), startDate = momentStart.date();
      let endYear = momentEnd.year(), endMonth = momentEnd.month(), endDate = momentEnd.date(), endDaysInMonth = momentEnd.daysInMonth();
      // 计算两个日期相差月份
      let start = moment([startYear, startMonth, startDate]);
      let end = moment([endYear, endMonth, endDate]);
      let diff = end.diff(start, 'months', true); // 两个日期相差月份
      // 日期:开始月+相差月 用于与结束日期做比较
      let startAddDiff = moment(startTime).add(Math.ceil(diff), 'months').subtract(1, 'days');
      let startAddDiffDate = startAddDiff.date();
      // 日期(结束月上一个月):开始月+(相差月-1)
      let lastEnd = moment(startTime).add(Math.ceil(diff) - 1, 'months').subtract(1, 'days');
      // 结束月上一个月日期 自然月天数
      let lastEndDate = lastEnd.date(), lastEndDaysInMonth = lastEnd.daysInMonth();
      // 开始月+相差月日期 === 结束月日期  则数量 = 相差月份
      if (startAddDiffDate === endDate) {
        amount = Math.ceil(diff);
      }
      // 开始月+相差月日期 < 结束月日期  则数量 = 相差月份 + (结束日期 - (开始月+相差月日期)) / 结束月自然月天数
      else if (startAddDiffDate < endDate) {
        amount = Math.floor(diff) + (endDate - startAddDiffDate) / endDaysInMonth;
      }
      // 开始月+相差月日期 > 结束月日期  则数量 = 相差月份 + (结束月自然月天数 - 结束月上一个月日期) / 结束月自然月天数 + 结束日期 / 结束月自然月天数
      else {
        amount = Math.floor(diff) + (lastEndDaysInMonth - lastEndDate) / lastEndDaysInMonth + endDate / endDaysInMonth;
      }
      return this.getRound(amount, 2);
    },
    /**
     * 四舍五入
     */
    getRound(num, len) {
      if (isNaN(num)) {
        return 0;
      }
      const p1 = Math.pow(10, len + 1);
      const p2 = Math.pow(10, len);
      return Math.round(num * p1 / 10) / p2;
    },
  }
}
```