获取日期间隔内的重复日期

我想我被这个问题困住了,所以我希望你能给我一些如何解决这个任务的想法。


我正在开发一个应用程序,它可以让您大致了解您的定期付款(我知道,这些东西已经存在,这只是一个副项目)和您的费用。


API 快要完成了,但我在这部分挣扎:我需要知道在给定的时间跨度内是否需要定期付款。


重复事件(合同)包含其他字段 startDate、endDate、intervalType(枚举 [每周、每月、每季度、每半年、每年])


目前我有这个作为我的学说查询:


return $this->createQueryBuilder('e')

    ->andWhere('e.startDate >= :start')

    ->andWhere('e.endDate <= :end')

    ->andWhere('e.user = :user')

    ->setParameter('start', $start)

    ->setParameter('end', $end)

    ->setParameter('user', $user)

    ->getQuery()

    ->getResult();

其中参数 start 和 end 是间隔帧。


但是我如何检查合同是否在选定框架内到期以及多久到期?


Afaik 这只能通过迭代查询结果并检查合同是否与时间范围相交并注意在此期间发生的频率和时间来实现。


但我不知道我怎么能做到这一点。


示例数据:


[name, intervalType, startDate, endDate, amount]

rent, monthly, 2019-01-01, 2020-10-11, -500

utility, monthly, 2019-01-01, 2020-10-11, -150

salary, monthly, 2019-01-01, 2020-10-11, 1700

investment, biannually, 2019-02-10, null , 2500

food, weekly, 2019-01-01, null , -50

如果我有这个月的时间表(2019-05-01 - 2019-05-31),我会得到这些合同:


rent 2019-05-01

utility  2019-05-01

salary 2019-05-01

food 2019-05-01

food 2019-05-08

food 2019-05-15

food 2019-05-22

food 2019-05-29

如果我选择以下 2 个月(2019-07-01 - 2019-08-31),我会得到这个:


rent 2019-07-01

rent 2019-08-01

utility  2019-07-01

utility  2019-08-01

salary 2019-07-01

salary 2019-08-01

food 2019-07-01

food 2019-07-08

food 2019-07-15

food 2019-07-22

food 2019-07-29

food 2019-08-01

food 2019-08-08

food 2019-08-15

food 2019-08-22

food 2019-08-29

investment 2019-08-01

DateTime 和 DateInterval 可以实现吗?


森林海
浏览 119回答 1
1回答

慕村9548890

每周间隔的逻辑在我看来是错误的。至少在我的银行应用程序中,每周计划总是在同一个工作日,两次连续发生之间有 7 天。因此,根据该逻辑,您可以使用此功能:function getScheduleBetween($data, $intervalStart, $intervalEnd) {&nbsp; &nbsp; $ref = [&nbsp; &nbsp; &nbsp; &nbsp; "yearly" => [12, "months"],&nbsp; &nbsp; &nbsp; &nbsp; "annually" => [12, "months"],&nbsp; &nbsp; &nbsp; &nbsp; "biannually" => [6, "months"],&nbsp; &nbsp; &nbsp; &nbsp; "quarterly" => [3, "months"],&nbsp; &nbsp; &nbsp; &nbsp; "monthly" => [1, "months"],&nbsp; &nbsp; &nbsp; &nbsp; "weekly" => [7, "days"],&nbsp; &nbsp; &nbsp; &nbsp; "daily" => [1, "days"]&nbsp; &nbsp; ];&nbsp; &nbsp; $intervalStart = new DateTime($intervalStart);&nbsp; &nbsp; $intervalEnd = new DateTime($intervalEnd);&nbsp; &nbsp; $result = [];&nbsp; &nbsp; foreach($data as $schedule) {&nbsp; &nbsp; &nbsp; &nbsp; // Convert start/end to DateTime&nbsp; &nbsp; &nbsp; &nbsp; $startDate = new DateTime($schedule["startDate"]);&nbsp; &nbsp; &nbsp; &nbsp; $endDate = $schedule["endDate"] ? min(new DateTime($schedule["endDate"]), $intervalEnd) : $intervalEnd;&nbsp; &nbsp; &nbsp; &nbsp; $name = $schedule["name"];&nbsp; &nbsp; &nbsp; &nbsp; $interval = $schedule["intervalType"];&nbsp; &nbsp; &nbsp; &nbsp; if (!isset($ref[$interval])) throw "Invalid interval type";&nbsp; &nbsp; &nbsp; &nbsp; list($coeff, $interval) = $ref[$interval];&nbsp; &nbsp; &nbsp; &nbsp; $match = clone $startDate;&nbsp; &nbsp; &nbsp; &nbsp; if ($match < $intervalStart) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $diff = $intervalStart->diff($match);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $count = $interval == "days" ? $diff->format("%a") : $diff->m + $diff->y * 12 + ($diff->d ? 1 : 0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $count = ceil($count / $coeff) * $coeff;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $match->modify("+$count $interval");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; while ($match <= $endDate) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $temp = clone $match;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result[] = ["name" => $name, "date" => $temp->format("Y-m-d")];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $match->modify("+$coeff $interval");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; array_multisort(array_column($result, "date"), $result);&nbsp; &nbsp; return $result;}使用示例:$data = [&nbsp; &nbsp; ["name" => "rent", "intervalType" => "monthly", "startDate" => "2019-01-01", "endDate" => "2020-10-11", "amount" => -500],&nbsp; &nbsp; ["name" => "utility", "intervalType" => "monthly", "startDate" => "2019-01-01", "endDate" => "2020-10-11", "amount" => -150],&nbsp; &nbsp; ["name" => "salary", "intervalType" => "monthly", "startDate" => "2019-01-01", "endDate" => "2020-10-11", "amount" => 1700],&nbsp; &nbsp; ["name" => "investment", "intervalType" => "biannually", "startDate" => "2019-02-10", "endDate" => null, "amount" => 2500],&nbsp; &nbsp; ["name" => "food", "intervalType" => "weekly", "startDate" => "2019-01-01", "endDate" => null, "amount" => -50],];$result = getScheduleBetween($data, "2019-05-01", "2019-05-31");print_r($result);随着更大的时期:$result = getScheduleBetween($data, "2019-05-01", "2019-08-31");print_r($result);如果您有其他类型的间隔,我相信您可以轻松扩展此功能以支持它们,即使使用“每周”的其他逻辑。
打开App,查看更多内容
随时随地看视频慕课网APP