У меня есть следующий массив:
Array ( [2010-10-30] => 1 [2010-11-11] => 1 [2010-11-13] => 11 )
Я пытаюсь заполнить массив всеми отсутствующими датами между первым и последним элементами. Я пытался использовать следующее, но не получил нигде:
foreach($users_by_date as $key => $value){ $real_next_day = date($key, time()+86400); $array_next_day = key(next($users_by_date)); if($real_next_day != $array_next_day){ $users_by_date[$real_next_day] = $value; } }
Классы DateTime, DateInterval и DatePeriod действительно могут помочь здесь.
$begin=date_create('2010-10-30'); $end=date_create('2010-11-13'); $i = new DateInterval('P1D'); $period=new DatePeriod($begin,$i,$end); foreach ($period as $d){ $day=$d->format('Ym-d'); $usercount= isset($users_by_date[$day]) ? $users_by_date[$day] :0; echo "$day $usercount"; }
Я ждал возможности опробовать объекты DateTime и DateInterval в PHP 5.3, ваш вопрос был прекрасной возможностью сделать именно это. Обратите внимание, что этот код не будет работать с версиями PHP раньше 5.3
<?php $dates = array('2010-10-30' => 1, '2010-11-01' => 1, '2010-11-13' => 1); // get start and end out of array reset($dates); $start = new DateTime(key($dates)); end($dates); $end = new DateTime(key($dates)); foreach (new DatePeriod($start, new DateInterval('P1D'), $end) as $date) { $dateKey = $date->format('Ym-d'); // get properly formatted date out of DateTime object if (!isset($dates[$dateKey])) { $dates[$dateKey] = 1; } } print_r($dates);
Функции, которые вы ищете (но не используете в вашем примере), – strtotime & diff
Вы получите дневной диапазон между двумя датами $numdiff
и просто сделайте что-нибудь в цикле, который будет делать:
for ($i=1; $i<=$numdiff; $i++) { echo date("Ymd", strtotime("2010-10-30 +".$i." day")); }
Результат должен выглядеть примерно так:
2010-10-31 2010-11-01 2010-11-02...
Затем вы можете поместить это в свой массив по мере необходимости. Надеюсь, что вы начнете в правильном направлении.
Для индексов, использующих временные метки, вы можете легко сгенерировать свой массив, используя функцию диапазона.
$startStamp = ... $endStamp = ... $oneDay = 60*60*24; $timeIndexes = range($startStamp, $endStamp, $oneDay); $filler = array_fill(0, count($timeIndexes), null); $timeArray = array_combine($timeIndexes, $filler);
Я не уверен, какие значения вы хотите в массиве, но, надеюсь, это относительно прямолинейно отсюда.
Если вы собираетесь конвертировать каждую временную метку в форматированную строку даты в любом случае и просто предпочтет использовать строки даты в первую очередь, рассмотрите эту модификацию.
$dateStringIndexes = array_map( function ($t) { return date('Ym-d', $t); }, $timeIndexes );
Конечно, поскольку вы находитесь на PHP 5.2, вам, скорее всего, придется идти на компромисс с циклом foreach, а не с закрытием.
Это функция, поддерживающая PHP 5.2. Я придумал, что работает.
Спасибо, парни
reset($users_by_date); $date = key($users_by_date); end($users_by_date); $end = key($users_by_date); while(strtotime($date) <= strtotime($end)){ $datearray[] = date("Ymd", strtotime($date)); $date = date("Ymd", strtotime("+1 day", strtotime($date))); } foreach($datearray as $key => $value){ if(!isset($users_by_date[$value])){ $users_by_date[$value] = 0; } } ksort($users_by_date);