一个订单算法的问题,有大佬看下怎么解不?

118 阅读6分钟

一个纠结了很久的算法问题

image.png

传入参数:

$serverBeginDateTime:int(服务开始时间戳)

$serverEndDateTime:int(服务结束时间戳)

说明:

  1. 时间上均是未满一小时按一小时计算,向上取整。
  2. 边界性计价也是未满一小时按一小时计算,例如:订单总时长为4个小时,其中1.5个小时在正常使用,2.5小时在禁用时间段,则总时长应该为2小时为正常计价,3小时为惩戒性计价。
  3. 函数最终应该得出八个返回值,分别是:
    1. 总使用时长(精确到秒)
    2. 总使用计价(单位:分)
    3. 正常使用计价总时长(精确到秒)
    4. 正常计价总价(单位:分)
    5. 禁用时间段内使用总时长(精确到秒)
    6. 禁用时间段惩戒性计价(单位:分),
    7. 正常使用计价时间段(对象)
      1. 正常使用:(array)
        1. 开始时间
        2. 结束时间
        3. 该阶段收费
      1. 禁用时间段使用:(array)
        1. 开始时间
        2. 结束时间
        3. 该阶段收费(下面是例子)
{
  "normal": [
    {
      "beginTime": "2024年11月3日 16:30:00",
      "endTime": "2024年11月3日 21:29:59",
      "amount": 25
    },
    {
      "beginTime": "2024年11月4日 06:30:00",
      "endTime": "2024年11月4日 21:29:59",
      "amount": 30
    },
    {
      "beginTime": "2024年11月5日 06:30:00",
      "endTime": "2024年11月5日 21:29:59",
      "amount": 30
    }
  ],
  "disable": [
    {
      "beginTime": "2024年11月3日 21:30:00",
      "endTime": "2024年11月4日 06:29:59",
      "amount": 90
    },
    {
      "beginTime": "2024年11月4日 21:30:00",
      "endTime": "2024年11月5日 06:29:59",
      "amount": 90
    },
    {
      "beginTime": "2024年11月5日 21:30:00",
      "endTime": "2024年11月5日 23:15:00",
      "amount": 20
    }
  ]
}

条件:

  1. 如果存在禁用时间段(isDisableTime = true),则该笔订单禁用时间段期间的时间占用按照(fine)收费
    1. 禁用时间段总价=订单在禁用时间段内占用的时长总数(单位小时)*禁用时间段内使用收费价格
    2. 如果禁用结束时间(disableEndTime)小于禁用开始时间(disableStartTime),则代表存在跨凌晨的情况,代表是次日时间。
  1. 正常使用时间段内需要考虑几种情况:
    1. 循环周期内的封顶计价(capedPrice)
    2. 循环周期外的未达到下一个计价周期中封顶计价时的计价(overtimePrice)
  1. 订单不存在暂停的情况,只有开始和结束时间。

情况模拟:

假设参数列举如下:

    1. 计费周期(billingCycle)的值为 2(两小时计费一次)
    2. 单次计费周期收费价格(price)收费:每2小时 5元
    3. 单次计费周期内收费封顶价格(capedPrice):800分(8元)/2小时
    4. 单次计费周期外价格收费(overtimePrice):600分(6元)/小时
    5. 禁用时间段开始时间(disableStartTime)为:每天18:00
    6. 禁用时间段结束时间(disableEndTime)为:早上8:00(当disableEndTime > disableStartTime时,disableEndTime为次日)
    7. 禁用时间段(fine)内收费 1000分(10元)/小时

变量说明:

    1. n1 是计费周期内封顶价格的循环次数
    2. n2 是超出计费周期后每小时价格的循环次数
    3. n3 是禁用时间段内惩罚性计价的循环次数

1. 情况一(未占用禁用时间,且仅在一个计费周期内,未触及封顶价格):

    1. 订单于2024年11月1日 17:01:55开始
    2. 订单于2024年11月1日 17:26:26结束
    3. 计算公式:price * 1 = amout

2. 情况二(未占用禁用时间,且仅在一个计费周期内,有触及封顶价格):

    1. 订单于2024年11月1日 16:01:55开始
    2. 订单于2024年11月1日 17:26:26结束
    3. 计算公式:capedPrice * 1 = amout

3. 情况三(占用了一个禁用时间,且在一个计费周期内,未触及封顶价格):

    1. 订单于2024年11月1日 17:50:55开始
    2. 订单于2024年11月1日 18:56:26结束
    3. (price * 1)+(fine * 1) = amout

4. 情况四(占用了一个禁用时间,且在一个计费周期内,有触及封顶价格)

    1. 订单于2024年11月1日 16:50:55开始
    2. 订单于2024年11月1日 18:32:26结束
    3. (capedPrice * 1)+ (fine * 1) = amout

5. 情况五(未占用禁用时间,有多个计费周期,且超出的计费周期触及封顶价格)

    1. 订单于2024年11月1日 14:50:55开始
    2. 订单于2024年11月1日 17:45:32结束
    3. 计算公式:(capedPrice * n1) = amout

6. 情况六(未占用禁用时间,有多个计费周期,且超出的计费周期未满封顶价格)

    1. 订单于2024年11月1日 15:50:55开始
    2. 订单于2024年11月1日 17:56:32结束
    3. 计算公式:(capedPrice * n1) + (overtimePrice * 1) = amoutfine

7. 情况七(占用了一个禁用时间,有多个计费周期,且超出的计费周期触及满封顶价格)

    1. 订单于2024年11月1日 14:50:55开始
    2. 订单于2024年11月1日 18:45:32结束
    3. 计算公式:(capedPrice * n1) + (overtimePrice * n2)+ (fine * 1)= amout

8. 情况八(占用了一个禁用时间,有多个计费周期,且超出的计费周期未满封顶价格)

    1. 订单于2024年11月1日 13:50:55开始
    2. 订单于2024年11月1日 17:55:32结束
    3. 计算公式:(capedPrice * n1) + (overtimePrice * 1)+ (fine * 1)= amout

9. 情况九(占用了多个禁用时间,有多个计费周期,且超出的计费周期触及满封顶价格)

    1. 订单于2024年11月1日 14:50:55开始
    2. 订单于2024年11月5日 18:45:32结束
    3. 计算公式:(capedPrice * n1) + (fine * n3)= amout

10. 情况十(占用了多个禁用时间,有多个计费周期,且超出的计费周期未满封顶价格有多个)

    1. 订单于2024年11月1日 14:50:55开始
    2. 订单于2024年11月4日 17:55:32结束
    3. 计算公式:(capedPrice * n1) + (overtimePrice * n2)+ (fine * n3)= amout