PHP计算X周的每周四和周日的日期

时间:2014-05-16 15:26:13

标签: php datetime

我已经在PHP中为在线电子竞技联盟编写了一个循环赛锦标赛生成器,我需要计算锦标赛中每场比赛的日期。游戏在每周四和周日进行,持续数周(周数取决于参与的团队数量)。 考虑到开始周数和周数,计算这些日期的最佳方法是什么?

我猜它需要使用DateTime,DateInterval和DatePeriod的某种组合;但我无法弄清楚它是如何完成的。

更新 抱歉不提供以前的代码。这是我最初提出的解决方案。我不知道是否有更简单的方法。该函数名为submitSchedule,其中生成了日期。

<html>
<body>

<?php

function roundRobin($teams) {
    $len = count($teams);
    $schedule = array();

    for ($i = 0; $i < $len - 1; $i++)
    {
        $home = array_slice($teams, 0, $len / 2);
        $away = array_slice($teams, $len / 2);
        $day = array();

        for ($j = 0; $j < $len / 2; $j++)
        {
            array_push($day, array($home[$j], $away[$j]));
        }

        array_push($schedule, $day);

        $temp = $away[0];

        for ($j = 0; $j < count($away) - 1; $j++)
        {
            $away[$j] = $away[$j + 1];
        }

        $away[count($away) - 1] = $home[count($home) - 1];

        for ($j = count($home) - 1; $j > 1; $j--)
        {
            $home[$j] = $home[$j - 1];
        }

        $home[1] = $temp;

        $teams = array_merge($home, $away);
    }

    return $schedule;
}

function roundRobinBalanced($teams)
{
    $schedule = roundRobin($teams);

    for ($i = 1; $i < count($schedule); $i+=2)
    {
        $schedule[$i][0] = array_reverse($schedule[$i][0]);
    }

    return $schedule;
}

function doubleRoundRobinBalanced($teams)
{
    $sched2 = roundRobinBalanced($teams);

    for ($i = 0; $i < count($sched2); $i++)
    {
        $sched2[$i] = array_reverse($sched2[$i]);
    }
    return array_merge(roundRobinBalanced($teams), $sched2);
}

function tripleRoundRobinBalanced($teams)
{
    return array_merge(doubleRoundRobinBalanced($teams), roundRobinBalanced($teams));
}

function submitSchedule($schedule, $start, $intervals, &$con)
{
    mysqli_query($con, "TRUNCATE TABLE matches");
    $curDate = $start;
    echo "<pre>";
    for ($i = 0; $i < count($schedule); $i++)
    {
        for ($j = 0; $j < count($schedule[$i]); $j++)
        {
            $temp0 = $schedule[$i][$j][0];
            $temp1 = $schedule[$i][$j][1];
            $temp2 = date_format($curDate, "Y-m-d");
            mysqli_query($con,"INSERT INTO matches (T1ID, T2ID, gameDate) VALUES ('$temp0', '$temp1', '$temp2')");
            echo "<span style=\"background:lightblue;\">( " . date_format(new DateTime(), "Y-m-d H:i:s") . " )</span>" . "> INSERT INTO matches (T1ID, T2ID, gameDate) VALUES (". $schedule[$i][$j][0] . ", " . $schedule[$i][$j][1] . ", \"" . date_format($curDate, "Y-m-d") . "\")<br>";
        }

        date_add($curDate, date_interval_create_from_date_string($intervals[$i % count($intervals)]));
    }
    echo "</pre>";
}

$teams = array();

$con=mysqli_connect("localhost:3306","root","REMOVED","schedule");
// Check connection
if (mysqli_connect_errno()) {
    echo "Failed to connect to MySQL: " . mysqli_connect_error();
}

//Select all items from the 'teams' table and order them first in descending order by points, then in ascending order by 'teamName'
$result = mysqli_query($con,"SELECT * FROM teams");

while($row = mysqli_fetch_array($result))
{
    array_push($teams, $row['TID']);
}

if (count($teams) % 2 == 1)
{
    array_push($teams, null);
}
shuffle($teams);

$schedule = tripleRoundRobinBalanced($teams);

// echo "<pre>" . json_encode($schedule, JSON_PRETTY_PRINT, JSON_FORCE_OBJECT) . "</pre>";

echo "<pre>";
print_r($schedule);
echo "</pre>";

// ---- List of possible DateTime expressions ----
// thursday
// next thursday
// YYYY-MM-DD
// DD/MM/yy
// thursday + 1 day

$start = new DateTime("thursday"); // Indicates the date of the first game
$jump = array("3 days", "4 days"); // Indicates the time intervals of each game (e.g. If day 1 starts on thursday, day 2 starts on sunday, day 3 starts on thursday, etc.)

submitSchedule($schedule, $start, $jump, $con);

mysqli_close($con);
?>
</body>
</html>

3 个答案:

答案 0 :(得分:1)

实现这一目标的方法是在猜测时使用PHP的DateTime类。它们真的很有用。我会建议一个像这样的小功能: -

/**
 * @param $startWeek ISO week number of the first week
 * @param $numWeeks  The number of weeks to run including the first
 *
 * @return \DateTime[] An array of DateTime objects
 */
function getPlayDays($startWeek, $numWeeks)
{
    $numWeeks --;
    $result = [];
    $currYear = (int)(new \DateTime())->format('Y');
    $oneDay = new \DateInterval('P1D');
    // Start on the first Thursday of the given week.
    $startDate = (new \DateTime())->setISODate($currYear, $startWeek, 4);

    $endDate = clone $startDate;
    $endDate->add(new \DateInterval("P{$numWeeks}W"));

    // End on the Sunday of the last week.
    $endDate->setISODate((int)$endDate->format('o'), (int)$endDate->format('W'), 7);

    $period = new \DatePeriod($startDate, $oneDay, $endDate->add($oneDay));

    foreach($period as $day){
        if(4 === (int)$day->format('N') || 7 === (int)$day->format('N') ){
            $result[] = $day;
        }
    }
    return $result;
}

foreach(getPlayDays(1, 3) as $playDay){
    var_dump($playDay->format('D m-d-Y'));
}

您没有指定如何识别起始周,因此我假设了ISO周编号。

输出: -

string 'Thu 01-02-2014' (length=14)
string 'Sun 01-05-2014' (length=14)
string 'Thu 01-09-2014' (length=14)
string 'Sun 01-12-2014' (length=14)
string 'Thu 01-16-2014' (length=14)
string 'Sun 01-19-2014' (length=14)

See it working

DateTime manual

由于DateTime类的内置魔力,这个函数非常乐意应对DST的变化,闰年接近一年的开始和结束:)

proof or STFU

答案 1 :(得分:0)

看一下strtotime功能:

http://www.php.net/manual/en/function.strtotime.php

你可以这样做:

$startDate = "May 15, 2014";
$startDate = strtotime($startDate);

你可以通过简单地添加三天来获得周日比赛的开始:

$nextDate = strtotime("+3 day", $startDate);

你的问题有点模糊,但我认为这就是你所要求的。

答案 2 :(得分:-1)

假设您有开始一周的时间戳(06:00 AM时间)... 每隔一个日期将是7天(86400秒* 7)。

假设您将运行52周(1年)

$firstThu = 1234567890;
$firstSun = 9876543210;

$nextThus = array();
$nextSuns = array();

for($i=0; $i<52; $i++) {
    $nextThus[] = date('d/m/Y', $firstThu + (86400 * 7 * $i));
    $nextSuns[] = date('d/m/Y', $firstSun + (86400 * 7 * $i));
}

在循环结束时,您将拥有两个阵列,其中包含52周的所有日期。