动态日期定义和条件


Dynamic date definition and conditions

我正在构建一个小班组合来计算学期开始的精确日期。决定学期开始的规则如下:

The monday of week number ## and after dd-mm-yyyy date
ie: for winter its week number 2 and it must be after the january 8th of that year

我正在构建一个资源类,其中包含所有学期(总共4个学期)的这些数据。但现在我面临着一个基于public holidays的问题。因为其中一些可能是在周一,在这些情况下,我需要得到周二的日期。

我目前正在处理的问题如下:

The target semester begins on or after august 30 and must be on week 35. 

我还必须考虑到9月的第一个星期一是公共假期。

PHP术语中的条件如下

if (date('m', myDate) == 9 // if the month is september
    && date('w', myDate) == 1 // if the day of the week is monday
    && date('d', myDate) < 7 // if we are in the first 7 days of september
)

把这个"词"作为条件并存储在数组中的最好方法是什么?

编辑

我可能说得不够清楚,找到日期不是问题。实际的问题是在配置数组中存储一个条件,如下所示:

$_ressources = array(
    1 => array(
        'dateMin' => '08-01-%',
        'weekNumber' => 2,
        'name' => 'Winter',
        'conditions' => array()
    ),
    2 => array(
        'dateMin' => '30-04-%',
        'weekNumber' => 18,
        'name' => 'Spring',
        'conditions' => array()
    ),
    3 => array(
        'dateMin' => '02-07-%',
        'weekNumber' => 27,
        'name' => 'Summer',
        'conditions' => array()
    ),
    4 => array(
        'dateMin' => '30-08-%',
        'weekNumber' => 35,
        'name' => 'Autumn',
        'conditions' => array("date('m', %date%) == 9  && date('w', %date%) == 1 && date('d', %date%) < 7")
    )
);

我对它现在呈现的方式的问题是,我将不得不使用eval()函数,我宁愿不使用。

你说:

目标学期在8月30日或之后开始,必须在第35周。

如果是这种情况,您可以简单地检查周数。

if(date('W', myDate) == 35)

或者如果你的测试条件是正确的,那么你应该比较天数直到7,因为它从1开始。

if((date('m', myDate) == 9 // september
    && date('w', myDate) == 1 // monday
    && date('d', myDate) <= 7 // first 7 days of september
)

然后在if语句中,一旦你找到了星期一(如果不是公共假日的话),执行

if(...){
    while(!array_search (myDate, aray_of_public_holidays))
        date_add($myDate, date_interval_create_from_date_string('1 days'));
}

这里的array_of_public_holidays包含公共假日列表。

用代码更新
下面的代码应该可以满足您的目的

<?php
    // array with public holidays
    $public_holidays = array(/* public holidays */);
    // start on 30th august
    $myDate = new DateTime('August 30');
    // loop till week number does not cross 35
    while($myDate->format('W') <= 35){
        // if its a monday
        if($myDate->format('w') == 1){
            // find the next date not a public holiday
            while(array_search($myDate, $public_holidays))
                $myDate->add(date_interval_create_from_date_string('1 days'));
            // now myDate stores the valid semester start date so exit loop
            break;
        }
        // next date
        $myDate->add(date_interval_create_from_date_string('1 days'));
    }
    // now myDate is the semester start date
?>

根据更新的问题进行更新
下面的代码应该可以满足您的需求。您不需要将条件以PHP代码的形式存储在数组中。下面的代码显示了如何实现

// semester conditions
$sem_conditions = array(
    1 => array(
        'dateMin' => '08-01-%',
        'weekNumber' => 2,
        'name' => 'Winter'
    ),
    2 => array(
        'dateMin' => '30-04-%',
        'weekNumber' => 18,
        'name' => 'Spring'
    ),
    3 => array(
        'dateMin' => '02-07-%',
        'weekNumber' => 27,
        'name' => 'Summer'
    ),
    4 => array(
        'dateMin' => '30-08-%',
        'weekNumber' => 35,
        'name' => 'Autumn'
    )
);
// array with public holidays format (d-M)
$public_holidays = array('05-09', '10-01');
// store sem starts
$sem_starts = array();
// for each semester
foreach($sem_conditions as $sem){
    // start date
    $myDate = date_create_from_format('d-m', substr($sem['dateMin'], 0, -2));
    // loop till week number does not cross $sem['weekNumber']
    while($myDate->format('W') <= $sem['weekNumber']){
        // if its a monday
        if($myDate->format('w') == 1){
            // find the next date not a public holiday
            while(array_search($myDate->format('d-m'), $public_holidays) !== false)
                $myDate->add(date_interval_create_from_date_string('1 days'));
            // now myDate stores the valid semester start date so exit loop
            break;
        }
        // next date
        $myDate->add(date_interval_create_from_date_string('1 days'));
    }
    // add to sem starts
    $sem_start[$sem['name']] = $myDate->format('d-m-Y');
}
var_dump($sem_start);

目标学期于8月30日或之后开始,必须在第35周

学期开始是在第35周到8月30日之间的最小日期:

$week35 = new DateTime("January 1 + 35 weeks");
$august30 = new DateTime("August 30");
$start = min($week35, $august30);

另外:

$start = min(date_create("January 1 + 52 weeks"), date_create("August 30"));