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