Я отправляю более раннюю дату, и она возвращает мне периоды между более ранней датой и сегодняшним днем, сокращенные на десятки дней.
Пример с 14.01.2016
Мне нужно, чтобы результат был точно таким, как показано ниже:
Вот мой код:
function date_interval($startTime = false){
if( ! $startTime){
return array();
} else {
if(date('d',$startTime) < 10){
$actual = mktime(0, 0, 0, date('m',$startTime), 1, date('Y',$startTime));
} elseif(date('d',$startTime) < 20){
$actual = mktime(0, 0, 0, date('m',$startTime), 10, date('Y',$startTime));
} else {
$actual = mktime(0, 0, 0, date('m',$startTime), 20, date('Y',$startTime));
}
if(date('d',time()) < 10) {
$target = mktime(0, 0, 0, date('m',time()), 10, date('Y',time()));
} elseif(date('d',time()) < 20) {
$target = mktime(0, 0, 0, date('m',time()), 20, date('Y',time()));
} else {
$target = mktime(0, 0, 0, date('m',time())+1, 1, date('Y',time()));
}$current = $actual;
$last = $actual;
while($current < $target) {
if(date('d',$current) < 10){
$current = mktime(0, 0, 0, date('m',$current), 10, date('Y',$current));
} elseif(date('d',$current) < 20){
$current = mktime(0, 0, 0, date('m',$current), 20, date('Y',$current));
} else {
$current = mktime(0, 0, 0, date('m',$current)+1, 1, date('Y',$current));
}
$dateTime[date("Y-m-d", $last) .'~'. date("Y-m-d", $current)] = date('d M Y',$last) . ' - ' . date('d M Y',$current));
$last = $current;
}
}
return $dateTime;
}
Datetime — это дорогой класс из php, который хорошо решает эту проблему.
Здесь вы передаете начальную дату функции как объект DATETIME, и функция отбрасывает стек тегов списка.
В цикле startDay изменяется сначала, добавляя 10 дней, чтобы совершить прыжок, а затем на один, чтобы избежать перекрытия.
Если вы хотите получить последнюю строку с периодом времени (менее десяти дней) с последнего дня начала до сегодняшнего дня, вы можете добавить что-то вроде:
$return .= '<li>From '.$startDay->format('d M Y').' to '.$today->format('d M Y').'</li>';
после цикла
function date_interval(DATETIME $startDay = NULL)
{
if( NULL == $startDay){
return array(); }
$return = '';
$today = new DATETIME('now');
while( $today->diff( $startDay )->format('%a%') > 10 )
{
$return .= '<li>From '.$startDay->format('d M Y').' to ';
$startDay->modify('+10 days');
$return .= $startDay->format('d M Y').'</li>
';
$startDay->modify('+1 day');
}
return $return;
}
Я изменил приведенное выше более общее решение, чтобы сделать именно то, что вы описываете:
<?php
function date_interval(DATETIME $startDay = NULL)
{
if( NULL == $startDay){
return array(); }
$return = '';
$today = new DATETIME('now');
$startMonth = new DateTime('first day of '.$startDay->format('M Y') );
$firstRun = TRUE;
while( $today > $startDay )
{
$return .= '<li>From '.$startDay->format('d M Y').' to ';
if( $firstRun == TRUE ){
if( (int)$startDay->format('d') > 10 )
$startMonth->modify('+10 days');
if( (int)$startDay->format('d') > 20 )
$startMonth->modify('+10 days');
$startDay = $startMonth;
$firstRun = FALSE;
}
$lastOfMonth = new DateTime('last day of '.$startDay->format('M Y') );
if( $lastOfMonth->diff( $startDay )->format('%a%') > 10 )
$startDay->modify('+9 days');
else
$startDay = $lastOfMonth;
$return .= $startDay->format('d M Y').'</li>
';
$startDay->modify('+1 day');
}
return $return;
}
echo date_interval( date_create_from_format('Y-m-d','2016-01-21') )."\n";
?>
Смотрите эту функцию, используя DateTime
:
function date_interval( $start = Null )
{
if( !$start ) return array();
$cur = new DateTime( sprintf( '%s-%02d', $start->format('Y-m'), [1,11,21,21][ floor(($start->format('j')-1)/10) ] ) );
$end = new DateTime();
$retval = [];
while( $cur <= $end )
{
$key = $cur->format( 'Y-m-d~' );
$val = $cur->format( 'd M Y - ' );
if( $cur->format( 'j' ) > 20 ) $cur->modify( 'last day of this month' );
else $cur->modify( '+ 9 days' );
$retval[ $key.$cur->format( 'Y-m-d' ) ] = $val.$cur->format( 'd M Y' );
$cur->modify( '+ 1 days' );
}
return $retval;
}
Называя это таким образом:
$startDate = '14/01/2016';
$array = date_interval( DateTime::createFromFormat( 'd/m/Y', $startDate ) );
print_r( $array );
В соответствии с вашей схемой ключей / значений, результирующий массив:
Array
(
[2016-01-11~2016-01-20] => 11 Jan 2016 - 20 Jan 2016
[2016-01-21~2016-01-31] => 21 Jan 2016 - 31 Jan 2016
[2016-02-01~2016-02-10] => 01 Feb 2016 - 10 Feb 2016
[2016-02-11~2016-02-20] => 11 Feb 2016 - 20 Feb 2016
[2016-02-21~2016-02-29] => 21 Feb 2016 - 29 Feb 2016
[2016-03-01~2016-03-10] => 01 Mar 2016 - 10 Mar 2016
[2016-03-11~2016-03-20] => 11 Mar 2016 - 20 Mar 2016
[2016-03-21~2016-03-31] => 21 Mar 2016 - 31 Mar 2016
[2016-04-01~2016-04-10] => 01 Apr 2016 - 10 Apr 2016
[2016-04-11~2016-04-20] => 11 Apr 2016 - 20 Apr 2016
[2016-04-21~2016-04-30] => 21 Apr 2016 - 30 Apr 2016
)
Мы работаем только на одну дату ($cur
), изначально созданный из переданного аргумента; мы устанавливаем день месяца, используя массив [1,11,21,21]
и выберите ключ с округленным делением на 10 от исходного дня (в вашем примере (14-1) / 10 = 1,3, округленное до 1, то есть 11 в [1,11,21,21]
массив). Это быстрый способ решить 31 день исключение.
Затем мы выполняем цикл до $cur
дата больше, чем сегодняшняя дата: мы создаем начальную часть ключа и значения, мы модифицируем $cur
добавив его девять дней или выбрав день прошлого месяца, мы создадим полный ключ и значение возвращаемого массива. В конце каждого цикла мы увеличиваем $cur
на 1 день.