2010-11-15 56 views
2

我有以下陣列:添加缺少的日期數組

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; 
    } 
} 
+0

是否有可能在第一和最後一個元素不是最低/最高的日期範圍?或者這將得到保證? – 2010-11-15 17:56:20

+0

它會被保證,有一個函數(ksort())在這之前,將無論如何排序,以防萬一! – user3450844 2010-11-15 17:58:45

+0

好的。給我一下,但就在我這樣做的時候,作爲一般規則,當你修改數組的鍵/索引時,不要使用foreach。 foreach只是枚舉元素並在迭代時「鎖定」元素更改(不是像鎖定副本那麼多,但可以用這些術語來考慮)。欲瞭解更多信息,請參閱PHP的foreach手冊:http://us3.php.net/manual/en/control-structures.foreach.php – 2010-11-15 18:04:15

回答

1

你正在尋找(但不是在你的例子使用)的功能是strtotime & diff

,你會得到你的兩個日期$numdiff之間的天範圍,並簡單地做一個循環的東西,會做:

for ($i=1; $i<=$numdiff; $i++) { 
    echo date("Y-m-d", strtotime("2010-10-30 +".$i." day")); 
} 

結果應該是這樣的:

2010-10-31 
2010-11-01 
2010-11-02... 

然後,您可以根據需要將其彈出到您的數組中。希望能讓你開始朝正確的方向發展。

+0

strtotime價格昂貴,但只要我們不擔心,這個解決方案似乎很好(對於PHP <5.3)。 – erisco 2010-11-15 18:39:14

8

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('Y-m-d'); 
    $usercount= isset($users_by_date[$day]) ? $users_by_date[$day] :0; 
    echo "$day $usercount"; 
} 
+0

不知道是什麼,但這是一個錯誤(除了不完整的新DatePeriod。) $ begin = date_create('2010-10-30'); \t \t $ end = date_create('2010-11-13') ; \t \t $ I =新DateInterval( 'P1D'); \t \t $週期=新DatePeriod($開始,$ I,$端); \t \t的foreach($週期爲$ d){ \t \t \t $ day = $ d-> format('Ym-d'); \t \t \t $ usercount = isset($ users_by_date [$ day] )? $ users_by_date [$ day]:0; \t \t \t echo「$ day $ usercount」; \t \t} \t \t print_r($ users_by_date); – user3450844 2010-11-15 18:13:06

+0

@SHutch:我吃了我的原始答覆。看起來我在重新創建時錯過了一些文字。現在修復。 – dnagirl 2010-11-15 18:18:08

+0

不幸的是,主機運行PHP v5.2.14,所以這不會工作:( – user3450844 2010-11-15 18:24:20

4

我一直在等待一個機會嘗試在PHP 5.3 DateTimeDateInterval對象,你的問題是要做到這一點的絕佳機會。請注意,此代碼不適用於早於5.3的PHP版本。

<?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('Y-m-d'); // get properly formatted date out of DateTime object 
    if (!isset($dates[$dateKey])) { 
     $dates[$dateKey] = 1; 
    } 
} 

print_r($dates); 
+0

不幸的是,主機運行PHP v5.2.14 :( – user3450844 2010-11-15 18:23:24

+1

+ 1爲日期範圍'foreach'循環,並將值添加到同一個數組。我仍然需要排序後的數組保持日期的順序,因爲它們被添加到最後。我有一個解決方案,我把它們複製過來,但更喜歡你的。 – philipp 2011-12-06 01:45:29

0

對於使用時間戳的索引,可以使用範圍函數輕鬆生成陣列。

$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('Y-m-d', $t); 
    }, 
    $timeIndexes 
); 

當然,由於您使用的是PHP 5.2,因此您可能必須使用foreach循環來代替閉包。

0

這是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("Y-m-d", strtotime($date)); 
     $date = date("Y-m-d", 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);