Php 计算预定义日期范围之间的天数

Php 计算预定义日期范围之间的天数,php,mysql,algorithm,sql-optimization,Php,Mysql,Algorithm,Sql Optimization,这是一个复杂的情况,我很抱歉。我有一个预订系统,可以预订房间 问题是房间的价格不是存储为单个值,而是基于时段的。比如,一个房间可以在9月到12月之间有一个每日费率,在3月到8月之间有一个不同的费率,而在其他方面有一个基本费率 费率表如下所示: ROOMID | RATE | PERIOD_START | PERIOD_END 假设3月1日至3月31日期间的房间价格为20美元/天,4月15日至5月30日期间的房间价格为30美元,但价格为15美元/天的固定价格 如果该房间在3月15日至5月10日期

这是一个复杂的情况,我很抱歉。我有一个预订系统,可以预订房间

问题是房间的价格不是存储为单个值,而是基于时段的。比如,一个房间可以在9月到12月之间有一个每日费率,在3月到8月之间有一个不同的费率,而在其他方面有一个基本费率

费率表如下所示:

ROOMID | RATE | PERIOD_START | PERIOD_END
假设3月1日至3月31日期间的房间价格为20美元/天,4月15日至5月30日期间的房间价格为30美元,但价格为15美元/天的固定价格

如果该房间在3月15日至5月10日期间由一位客户预订,总成本为:

15th March - 31st march charged at 20 Dollars/day = 16x20
1st April - 14th April charged at 15 Dollars/day = 14x15
15th April - 10th May charged at 30 Dollars/day = 25x30

现在我如何在代码中计算这个值,我需要根据利率周期(如果有)计算天数,否则使用基本利率。这很复杂,但事实就是这样。我使用的是php MySQL,一个可能的解决方案是创建一个名为price_periods的表,其中包含开始日期、结束日期、价格以及房间的引用

因此,SQL表将如下所示

价格周期

PPID | ROOM_ID | PP_START_DATE | PP_END_DATE | PP_PRICE
-------------------------------------------------------
1      2         09-20           10-20         15
2      2         10-21           11-20         20
然后,您只需计算预订已完成的日期,因此假设某人A想要从10-11到10-25租赁一个房间,他必须使用id 1支付价格周期,直到PP\U结束日期发生,然后使用id 2支付价格周期,直到预订结束。所以问题是,你可能会有两个以上的日期在任何时候工作

我想您的预订桌是这样的

预订

B_ID | ROOM_ID | USER_ID | START_DATE | END_DATE
------------------------------------------------
1      2         4         10-11        10-25
您必须进行计算,但有一个开始可能会起作用。

试试这个

这将循环浏览预订期间的每一天,从表中找到适当的费率,然后将其添加到总数中

$Day="2011-03-15";
$End="2011-05-10";
$Periods=array(); // Filled with the Mysql rows - mysql_fetch_assoc()
$Total=0;
编辑

更优化

foreach($Periods as $Period) {
    if($Day>=$Period['PERIOD_START']&&$Day<=$Period['PERIOD_END']) {
        while($Day<=$End&&$Day<=$Period['PERIOD_END']) {
            $Total+=$Period['RATE'];
            $Day=date('Y-m-d',strtotime("$Day +1 day"));
        }
    }
}
foreach($Periods as$Period){

如果($Day>=$Period['Period\u START']&&$Day这是一种可能的解决方案算法:

  • 查找与预订期间具有非空交叉点的所有费率期间
  • 对于(1)中的每个费率周期,计算其与预订周期相交的天数,并乘以周期费率
  • 剩余天数(即预订期的天数减去(2)中所有天数的总和)是您的基本费率天数
  • Re(1),为了找出哪些费率周期与预订周期相交,请注意,2个区间
    (A,B)
    (C,D)
    DB
    时有一个空的相交点,因此您可以直接否定此条件。应该类似于:

    SELECT * FROM rates 
       WHERE NOT (booking_end < period_start OR 
                  booking_start > period_end)
    
    从费率中选择*
    如果没有(预订结束<时段开始或
    预订(开始>时段结束)
    
    Re(2),您只需要找到
    max(预订开始,时段开始)
    min(预订结束,时段结束)
    之间的天数。我确信有一些实用程序可以处理日期,但在最坏的情况下,您可以循环查看它


    很抱歉,我不是一个编写实际代码的SQL/php向导…:)

    这里只给出了一个半认真的答案

    如果需要单个SQL查询,可以执行以下操作:

    SELECT SUM(IF(ISNULL(r.rate), 10, r.rate))
    FROM days AS d
    LEFT JOIN rates AS r ON d.d BETWEEN r.start AND r.end
      WHERE d.d BETWEEN '2011-03-15' and '2011-05-10';
    
    诀窍在于,您需要一个名为“days”的表,该表有一个日期字段d。预先填充该表,以包括从现在到永恒的每一天。通过脚本执行此操作很简单;您只需将未来的可预订日期保留在其中

    请注意,您在选择开始日期和结束日期时一定要小心。例如,如果您在3月31日和4月1日之间预订了一个房间,这到底意味着什么

    那是一天20美元和一天10美元?还是只有一天20美元?还是一天10美元

    它实际上并不影响这个答案本身,但它确实影响您如何构建费率表,以及您使用哪几天作为开始和结束日期

    此外,此版本假定rates字段使用完整的YYYY-MM-DD格式。这不是绝对要求,但如果只是MM-DD格式,则必须稍微修改联接


    就我个人而言,我不会这样做。相反,我会使用
    DateInterval
    类循环PHP代码中的日期,并以这种方式查询价格。

    在PHP中,您可以使用两个日期之间的间隔。

    可能重复的日期,因此问题是,一些要预订的日期可能在不同的价格/日期范围内就像3月31日前3天,4月1日后两天一样?@jonah-是的,正如你所说的it@Linus-该项目是相同的,但情况不同,即其关注的是根据不同时期的不同费率计算成本,其他问题都没有解决此问题如果您想优化此问题,您不会每次迭代都需要一步一步地完成每个周期。只需对周期进行排序,当您超过当前周期时,切换到下一个周期。如果
    $day<$period->start
    ,您将知道您是否处于两个周期之间($10)。将周期循环放在顶部可以对其进行更多优化。这样可以减少整个过程中不必要的循环。