Php 二月份
我试图根据日历日期范围计算每月重复发生的事件。然而,当某个事件发生在2月29日时,我偶然发现了一个问题,即2月(28天)的计算。希望一些专家能给我一些指点,因为我尝试在没有帮助的情况下四处搜索 为了便于直接作为脚本运行,我包含了以下代码。Php 二月份,php,recurring,Php,Recurring,我试图根据日历日期范围计算每月重复发生的事件。然而,当某个事件发生在2月29日时,我偶然发现了一个问题,即2月(28天)的计算。希望一些专家能给我一些指点,因为我尝试在没有帮助的情况下四处搜索 为了便于直接作为脚本运行,我包含了以下代码。1月范围工作正常,这给了我两个属于该范围的日期: // JANUARY 2013 Range (Working) 2012-12-29 2013-01-29 但如果取消注释二月范围,它将开始输出: 2013-01-29 // This is correct 2
1月
范围工作正常,这给了我两个属于该范围的日期:
// JANUARY 2013 Range (Working)
2012-12-29
2013-01-29
但如果取消注释二月范围,它将开始输出:
2013-01-29 // This is correct
2013-02-28 // This is the date which I want to ignore because its not on the 29th.
如果您取消对April
范围的注释,它将开始什么也不输出。它应该输出一个日期2013-04-29
。因此,我想问题在于计算
<?php
// Start Calendar Range
// JANUARY 2013 Range (Working)
$rangeStart = new DateTime( '2012-12-30' );
$rangeEnd = new DateTime( '2013-02-03' );
// FEBRUARY 2013 Range (Not Working)
//$rangeStart = new DateTime( '2013-01-27' );
//$rangeEnd = new DateTime( '2013-03-03' );
// APRIL 2013 Range (Not Working)
//$rangeStart = new DateTime( '2013-03-31' );
//$rangeEnd = new DateTime( '2013-04-05' );
// MAY 2013 Range (Working)
//$rangeStart = new DateTime( '2013-04-28' );
//$rangeEnd = new DateTime( '2013-06-02' );
// Event date start
$eventStart = new DateTime( '2012-10-29' );
$recurTimes = 1;
// Loop thru the days of month
while( $rangeStart->format('U') <= $rangeEnd->format('U') ) {
$currView = mktime( 0, 0, 0, $rangeStart->format('m'), $eventStart->format('d'), $rangeStart->format('Y') );
$interval = round(($currView-$eventStart->format('U')) / 60 / 60 / 24 / 30);
$monthsAway = $eventStart->format('m')+$interval;
$recurMonth = $eventStart->format('m')%$recurTimes;
if( $monthsAway%$recurTimes == $recurMonth ) {
$nextRecur = getNextRecur( $eventStart->format('U'), $interval );
echo date( 'Y-m-d', $nextRecur ) . '<br />';
}
$rangeStart->modify('+1 month');
}
// function to add 1 month with leap year in consideration
function getNextRecur( $baseTime=null, $months=1 ) {
if( is_null( $baseTime ) ) $baseTime = time( );
$xMonths = strtotime( '+' . $months . ' months', $baseTime );
$before = (int)date( 'm', $baseTime )+12*(int)date( 'Y', $baseTime );
$after = (int)date( 'm', $xMonths )+12*(int)date( 'Y', $xMonths );
if( $after > $months+$before ) {
$xMonths = strtotime( date('Ym01His', $xMonths) . ' -1 day' );
}
return $xMonths;
}
?>
也许你这样做是有原因的,但在我看来,这有点离谱。 我们都知道,所有的月份都是以天为单位的,二月是奇数。 所以我希望你能从这个角度来看 我并没有考虑我将如何“准确地”完成它,但我会将它简化为只在2月工作。 也许你可以先做一次年检,看看是不是闰年。然后让您的代码在插入2月的日期后执行所需的操作。您可以尝试 例1
$rangeStart = new DateTime('2012-12-30');
$rangeEnd = new DateTime('2013-02-03');
$eventStart = new DateTime('2012-10-29');
var_dump(getRange($rangeStart, $rangeEnd, $eventStart));
输出
array
0 => string '2013-01-29' (length=10)
例2
$rangeStart = new DateTime('2012-01-27');
$rangeEnd = new DateTime('2013-03-03');
$eventStart = new DateTime('2012-10-29');
var_dump(getRange($rangeStart, $rangeEnd, $eventStart));
输出
array
0 => string '2012-10-29' (length=10)
1 => string '2012-11-29' (length=10)
2 => string '2012-12-29' (length=10)
3 => string '2013-01-29' (length=10)
使用的功能
function getRange($rangeStart, $rangeEnd, $eventStart, $fixedDay = 29) {
$lastStart = clone $rangeStart;
$rangeStart->setDate($eventStart->format('Y'), $eventStart->format('m'), $eventStart->format('d'));
$list = array();
while ( $rangeStart <= $rangeEnd ) {
if ($rangeStart > $rangeEnd)
break;
if ($rangeStart->format('m') == 2 || $rangeStart < $lastStart) {
$rangeStart->modify('+1 month');
$rangeStart->setDate($rangeStart->format('Y'), $rangeStart->format('m'), $fixedDay);
continue;
}
$list[] = $rangeStart->format("Y-m-d");
$rangeStart->modify('+1 month');
$rangeStart->setDate($rangeStart->format('Y'), $rangeStart->format('m'), $fixedDay);
}
return $list;
}
函数getRange($rangeStart,$rangeEnd,$eventStart,$fixedDay=29){
$lastStart=克隆$rangeStart;
$rangeStart->setDate($eventStart->格式('Y'),$eventStart->格式('m'),$eventStart->格式('d');
$list=array();
而($rangeStart$rangeEnd)
打破
如果($rangeStart->format('m')==2 | |$rangeStart<$lastStart){
$rangeStart->修改(“+1个月”);
$rangeStart->setDate($rangeStart->格式('Y'),$rangeStart->格式('m'),$fixedDay);
继续;
}
$list[]=$rangeStart->格式(“Y-m-d”);
$rangeStart->修改(“+1个月”);
$rangeStart->setDate($rangeStart->格式('Y'),$rangeStart->格式('m'),$fixedDay);
}
返回$list;
}
测试了刚刚返回的代码。。2012-12-29 , 2013-01-29 .. 我想先关注一下代码的目标。。。什么是偶数间隔?为什么选择用整数计算?您需要取消对2013年2月范围的注释,它将输出2013-01-29和2013-02-28。2013-02-28是我希望忽略的日期。最初我使用的是ceil,但我在2月份也遇到了28天的问题。所以目前只有一轮似乎没有给问题。我想我现在明白了。。。。如果我错了,请纠正我。。应该显示
2013-02-28
而不是2013-03-01
对吗?不,我只想在每个月的29日显示活动。对于二月的情况,我希望它跳过,因为它没有第29个?这很容易。。但是你的代码让它变得复杂。。。。你想输出每个月的日期吗?这比在2月检查更复杂,因为如果不考虑2月的计算,就像我在第一篇文章中发布的那样,它会影响4月也不会输出事件。如果你只是不评论2月、3月、4月等等,最后一个变量值将覆盖最早的值。你是如何保持它们的独特性和连续性的?因为我正在做这样的工作,当你每月滚动时,范围可能从10月30日到11月10日或11月28日到12月8日开始。谢谢爸爸。但是,如果你尝试4月份的范围,它仍然不能提供任何输出。有什么想法吗?还有三月份,它给我的是2013-01-29,而不是2013-03-291。我总是跳过二月,即使你很生气。。您的活动日期也会影响输出…很抱歉,我在第一篇文章中没有包括三月范围。三月范围为$rangeStart=新日期时间('2013-02-24')$rangeEnd=新日期时间('2013-03-07')@袁芬:好的,让我来测试一下。。等等