Php 根据开始日期确定日期是否为每隔一周的一部分

Php 根据开始日期确定日期是否为每隔一周的一部分,php,date,datetime,Php,Date,Datetime,我有一些代码,从某个特定日期开始,在10年的范围内每天循环。仅当日期满足表单中的选定条件时,才应添加该日期 该表单包含要选择的月份和工作日字段。在每个工作日内,都有“每”、“第一”、“第二”等选项。我将在每个工作日添加一个“每隔一个”选项以及一个“开始日期”字段 我试图确定检查当前日期是否在基于开始日期的“每隔一天”标准内的最佳方法 在看了其他的问题后,我找不到一个理想的答案,因为这一年有53周。我能够想出一些测试代码,似乎给了我准确的结果,但我想知道是否有一个更简单的方法来执行这个检查 测试代

我有一些代码,从某个特定日期开始,在10年的范围内每天循环。仅当日期满足表单中的选定条件时,才应添加该日期

该表单包含要选择的月份和工作日字段。在每个工作日内,都有“每”、“第一”、“第二”等选项。我将在每个工作日添加一个“每隔一个”选项以及一个“开始日期”字段

我试图确定检查当前日期是否在基于开始日期的“每隔一天”标准内的最佳方法

在看了其他的问题后,我找不到一个理想的答案,因为这一年有53周。我能够想出一些测试代码,似乎给了我准确的结果,但我想知道是否有一个更简单的方法来执行这个检查

测试代码:

// set start date
$date = new \DateTime('2019-12-15');

// get start date week of year and modulus
$start_week = date('W', $date->getTimestamp());
$start_mod = $start_week % 2;

// set end time (10 years from start date)
$end_time = strtotime('+10 years', $date->getTimestamp());

// init previous year and week modifier
$prev_year = false;
$week_modifier = 1;

// each day in range
while($date->getTimestamp() <= $end_time){

    // get year
    $y = $date->format('Y');

    // previous year doesn't match current year
    if($prev_year != $y){

        // previous year set
        if($prev_year){

            // get number of weeks in year
            $weeks_in_year = date('W', mktime(0, 0, 0, 12, 28, $prev_year));

            // year has odd number of weeks
            if($weeks_in_year % 2){

                // increment week modifier
                $week_modifier++;

            }

        }

        // update previous year
        $prev_year = $y;

    }

    // get week of year
    $w = $date->format('W') + $week_modifier;

    // check if meets every other criteria (based on start date)
    $every_other = false;
    if( ($w % 2) == $start_mod ){
        $every_other = true;
    }

    // print date if it is part of every other Tuesday
    if($date->format('w') == 2 && $every_other){
        echo $date->format('Y-m-d');
        echo '<br/>';
    }

    // increment day
    $date->modify('+1 day');

}
//设置开始日期
$date=new\DateTime('2019-12-15');
//获取年度开始日期周和模数
$start_week=date('W',$date->getTimestamp());
$start\u mod=$start\u第%2周;
//设置结束时间(从开始日期算起10年)
$end_time=strottime(“+10年”,$date->getTimestamp());
//初始上一年和上一周修饰符
$prev_year=假;
$week_修饰符=1;
//每天都在范围内
而($date->getTimestamp()格式('Y');
//上一年与本年不匹配
如果($prev_year!=$y){
//上年度设定
如果(上一年){
//获取一年中的周数
$weeks_in_year=日期('W',mktime(0,0,0,12,28,$prev_year));
//一年有奇数周
如果($weeks\u in\u year%2){
//增量周修饰符
$week_修饰符++;
}
}
//上一年的更新
$prev_year=$y;
}
//获得一年中的一周
$w=$date->format('w')+$week\u修饰符;
//检查是否符合其他标准(基于开始日期)
$every_other=假;
如果($w%2)=$start\U mod){
$every_other=真;
}
//如果是每隔一个星期二打印一次日期
如果($date->format('w')==2&&$every_其他){
echo$date->format('Y-m-d');
回声“
”; } //增量日 $date->modify(“+1天”); }
注1:2020年是下一年,为期53周

注2:我在测试代码中有一个输入错误,它增加了week修饰符,而不是将其初始化为0。如果修饰符被初始化为0,那么这段代码会工作,这对我来说更有意义,但它只在初始化为奇数时工作。

因为“每隔一个”在一个连续的周期中进行评估,您可能只需跟踪天数:

$odd = [ true, true, true, true, true, true, true ];

...
// Flip the appropriate day of the week.
$odd[date('w')] = !$odd[date('w')];
// Or start with all 1's, then $odd[date('w')] ^= 1;

if ($odd[date('w')]) {
    // This is the "not-other" day
}
模运算 这一天是
$w
,我们将其标记为:

$odd[$w] = !$odd[$w];
现在我们前进了未知的天数
$d
。我们需要正确地翻转此间隔中的所有天数

一种方法是循环所有的日子。但很明显,这不是必须的-我们一周有七天,它们要么是奇数,要么是偶数;即使我们将它们全部翻转,也将是七次更新。循环一年将是365或366次更新

一方面,365周期解决方案具有简单性的优点。运行7次翻转而不是3652是否真的值得我们去做?如果不值得,我们就完成了。因此,让我们假设它是;但是每个项目都应该重新进行此评估

所以请注意,如果我们提前1天,我们什么都不需要做。如果我们提前2天,则必须翻转第[w+1]天。如果我们提前5天,则需要翻转从w+1到w+4的天数。通常,从w+1到w+d-1的天数需要翻转:

for ($i = 1; $i < $w+$d; $i++) {
    $odd[$i % 7] = !$odd[$i % 7];
}
因此,这里有一个非常合理的折衷方案:如果我们需要提前X天,请将其视为必须提前(X%14)天。因此,现在我们最多将运行13次更新。现在停止意味着我们的代码是微不足道的版本,通过战略性地放置“%14”进行了增强.我们每隔十年从3652次更新到14次更新,我们所能期望的最好结果是7次更新。我们几乎用很少的钱获得了所有的成功

如果我们只想满足于最好的,我们就继续(但请注意,额外的算法可能会比在更新中保存更昂贵,从最坏的值13保存到最多零。换句话说,进行额外检查意味着我们最多只能保存13次更新;如果这些检查花费超过13次更新,我们最好不要检查并盲目地进行)


因此,我们开始翻转dIndex 1 if(1=9),然后在(d%14)-1 if(d%14)结束我会考虑查看这个项目:它对处理递归很有帮助,这显示了可以使用的RRACE字符串的一些例子:……每星期一的一个字符串的缩减版本,看起来像这个代码< Frq=周刊;间隔=2;BayDay= Mo/Cube >(可以包括开始日期和结束日期等)谢谢@Theo。我不知道Recurr。我肯定会仔细研究这个问题,以解决这个问题和其他几个日期标准问题!太好了!非常简单可靠。谢谢。@Lsemi发现这对我的情况不起作用,因为有些情况下我需要一次增加一个月的日期。但我可能能够在将来使用你的建议。那样的话,我想用模运算可以做一些事情。我明天给你回复。
d      need to flip w+...
1      (none)
2      1
3      1, 2
4      1, 2, 3
5      1, 2, 3, 4
6      1, 2, 3, 4, 5
7      1, 2, 3, 4, 5, 6
8      1, 2, 3, 4, 5, 6, 0 (or 7)
9         2, 3, 4, 5, 6, 0
10           3, 4, 5, 6, 0
11              4, 5, 6, 0
12                 5, 6, 0
13                    6, 0
14                       0
15     (none)
// increase by d days
d1 = (d%14) < 9 ? 1 : (d%7);
d2 = (d%14) < 8 ? (d%14-1) : 7;

for (dd = d1; dd <= d2; dd++) {
    odd[(w+dd)%7)] = !odd[(w+dd)%7)];
}