Массив периодов времени с начальной и конечной датами по диапазону - PullRequest
0 голосов
/ 20 февраля 2019

Я хочу создать таблицу со значениями, основанными на массиве временных интервалов, который показывает даты начала и окончания каждого периода.Периоды могут быть с фиксированными интервалами, например (P1D, P1M и т. Д.).

У меня уже есть функция, которая генерирует закрытые (прошлые) периоды, но я не могу найти способ сделать это с будущими датами.

Это функция:

function interval($start, $interval, $break = 0)
{
    $result = array();

    $today = date("Y-m-d");
    if ($break == 0) {
        if ($today < $start) $break = 1;
    }

    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));

    $x = TRUE;
    if ($break == 0) {
        do {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array(
                'begin' => $f1,
                'end'    => $f2
            );
            $x = ($f1 <= $today && $f2 >= $today) ? TRUE : FALSE;
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

        } while (!$x);

    } else {

        for ($n = 1; $n <= $break; $n++) {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array(
                'begin' => $f1,
                'end'    => $f2
            );
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));
        }
    }
    return $result;
}

Для использования просто вызовите функцию:

print_r(interval('2019-01-01', 'P1M'));

И результат такой:

(
    [0] => Array
        (
            [begin] => 2019-01-01
            [end] => 2019-02-01
        )

    [1] => Array
        (
            [begin] => 2019-02-02
            [end] => 2019-03-01
        )

)

Я хочу сделать то же самое, но с будущими периодами, например, с 01-01-2019 по 01-01-2023 с интервалом в 1 месяц (P1M).

Обновление

Ответ @dWinder наиболее близок к решению, которое я ищу, без необходимости путешествовать во времени =), и оно очень хорошо работает с месячными и годовыми интервалами, но с более короткими периодами (P15D, P1W, P1D), скрипт представляет проблемы, которые я не могу определить.

Я обновил опубликованную вами функцию, чтобы она правильно проходила по массиву и оставалась так:

function interval($start, $interval, $maxPeriods = 100, $end = NULL) {
    $result = array();
    //$today = date("Y-m-d"); ** Variable not used, disable it **
    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));
    do {
        $date->add($interval);
        $f2 = $date->format('Y-m-d');
        $result[] = array( 'begin' => $f1, 'end' => $f2);
        if ($end <> NULL && $end == $f2) break; // if over the end date stop the loop
        $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

    } while (++$maxPeriods); // I changed -- to ++ to avoid stopping the loop
    return $result;
}

Обновленная функцияиспользуется следующим образом:

print_r(interval('2019-01-01', 'P1M', NULL, '2023-01-01'));

И результаты:

(
    [0] => Array
        (
            [begin] => 2019-01-01
            [end] => 2019-02-01
        )

    [1] => Array
        (
            [begin] => 2019-02-02
            [end] => 2019-03-01
        )

    [2] => Array
        (
            [begin] => 2019-03-02
            [end] => 2019-04-01
        )

    [3] => Array
        (
            [begin] => 2019-04-02
            [end] => 2019-05-01
        )

    [4] => Array
        (
            [begin] => 2019-05-02
            [end] => 2019-06-01
        )

    [5] => Array
        (
            [begin] => 2019-06-02
            [end] => 2019-07-01
        )

    [6] => Array
        (
            [begin] => 2019-07-02
            [end] => 2019-08-01
        )

    [7] => Array
        (
            [begin] => 2019-08-02
            [end] => 2019-09-01
        )

    [8] => Array
        (
            [begin] => 2019-09-02
            [end] => 2019-10-01
        )

    [9] => Array
        (
            [begin] => 2019-10-02
            [end] => 2019-11-01
        )

    [10] => Array
        (
            [begin] => 2019-11-02
            [end] => 2019-12-01
        )

    [11] => Array
        (
            [begin] => 2019-12-02
            [end] => 2020-01-01
        )
)...

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Лучшим решением будет посылать аргумент «конец» и проверять его (в дополнение к «maxPeriods»

Рассмотрим следующее (обратите внимание на комментарий в коде):

function interval($start, $interval, $maxPeriods = 100, $end = null) {
    $result = array();
    $today = date("Y-m-d");
    $date = new DateTime($start);
    $interval = new DateInterval($interval);

    $f1 = date('Y-m-d', strtotime($start));
    do {
            $date->add($interval);
            $f2 = $date->format('Y-m-d');
            $result[] = array( 'begin' => $f1, 'end' => $f2);
            if ($end && $end < $f2) break; // if over the end date stop the loop
            $f1 = date('Y-m-d', strtotime('+1 day', strtotime($f2)));

    } while (--$maxPeriods); //till you get max elements
    return $result;
}

Теперь назовите его с помощью

print_r(interval('2019-01-01', 'P1M', 48));
//or
print_r(interval('2019-01-01', 'P1M', null, "2023-01-01"));

Обратите внимание, что первая роль встречается с разрывом цикла (конечная дата или максимальное количество элементов)

0 голосов
/ 20 февраля 2019

Поможет машина времени :) Если программа правильно рассчитывает прошлые периоды, то, если бы она «думала», что сегодня был «2023-01-01» («дай или возьми»), она будет правильно рассчитывать прошлые периоды.Можете ли вы добавить $end аргумент, по умолчанию на сегодня?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...