繁体   English   中英

2月的定期月份

[英]Recurring Months of February

我正在尝试根据日历日期范围计算每月重复发生的事件。 但是,当事件在每月的29号发生时,我偶然发现February (28 days)计算存在问题。 希望在我没有帮助的情况下尝试搜索时,一些专家可以给我一些指导。

我包括以下代码,以便于直接作为脚本运行。 January范围工作正常,这给了我2个日期,该日期属于该范围:

// 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 因此,问题在于我想的2月计算。

<?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月为奇数。 因此,我想请您从那个角度来看它。

我还没有研究过我将如何“精确”地执行此操作,但是我将其简化为仅在二月份工作。 也许您可以进行年度检查,看看是否首先是a年。 然后让您的代码在插入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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM