2015-06-09 2 views
6

У меня есть код PHP для расчета количества дней между двумя конкретными датами. Разница не должна учитываться по воскресеньям и субботам. Кроме того, у меня есть набор дат, который включает в себя праздничные дни, которые также необходимо пропустить.Ошибка расчета разницы PHP-дней

Я дал стартовую дату как 01-05-2015 и дату окончания как 01-06-2015. Я дал целые дни в месяце май, как массив. Таким образом, разница должна быть 1 день. Но я получаю вывод как 7. В чем проблема? Вот код.

function dateRange($first, $last) { 
    $dates = array(); 
    $current = strtotime($first); 
    $now = $current; 
    $last = strtotime($last); 
    while($current <= $last) { 
     if (date('w', $current) != 0){ 
      $dates[] = date('d-m-Y', $current); 
     } 
     $current = strtotime('+1 day', $current); 
    } 
    unset($dates[0]); 
    return $dates; 
} 


$datea = "01-05-2015"; 
$date = "01-06-2015"; 
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015"); 

$datesarray = dateRange($datea, $date); 
$result = array_diff($hdsarray,$datesarray); 
$date_diff = sizeof($result); 

echo $date_diff; 

Заранее спасибо ... :)

+2

Здесь есть несколько проблем. Прежде всего, я начну с вопроса: почему вы устанавливаете $ date [0]? Тем не менее, array_diff не будет работать, потому что $ hsdarray date «1-05-2015» отличается от «01-05-2015», поэтому ваша разница не будет работать. Другая проблема: потому что вы исключаете воскресенья (и, возможно, субботы, но я не вижу этого в вашем коде), array_diff выведет AT LEAST: 16-05-2015 (суббота), 23-05-2015 (суббота) и 30-05-2015 (суббота). – briosheje

ответ

3

Проблема только я вижу в использовании array_diff, он на самом деле включает сат и солнце, которое исключается dateRange функции, если не найден в списке праздников ,

Вместо этого вы можете передать свои выходные дни в dateRange функции и отфильтровать там.

function dateRange($first, $last, $excludeDates) { 
    $dates = array(); 
    $current = strtotime($first); 
    $now = $current; 
    $last = strtotime($last); 
    while($current <= $last) { 
     if (date('w', $current) != 0 && date('w', $current) != 6 && !in_array(date('j-m-Y', $current), $excludeDates)){ 
      $dates[] = date('d-m-Y', $current); 
     } 
     $current = strtotime('+1 day', $current); 
    } 
    // unset($dates[0]); 
    return $dates; 
} 

$datea = "01-05-2015"; 
$date = "01-06-2015"; 
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015"); 
$datesarray = dateRange($datea, $date, $hdsarray);print_r($datesarray); 

Результат:

Array 
(
    [0] => 06-05-2015 
    [1] => 13-05-2015 
    [2] => 20-05-2015 
    [3] => 27-05-2015 
    [4] => 01-06-2015 
) 

Все 5 дат приходит в результате, не сидел, солнце, а также нет в списке праздников.

0

Похоже, здесь есть несколько проблем. Во-первых, как указывалось другими условие:

if (date('w', $current) != 0){ 

только чеки на воскресенье, если он должен также включать в себя субботу он должен быть:

if (date('w', $current) != 0 && date('w', $current) != 6){ 

Во-вторых, кажется, что $hdsarray массив не содержит все дни в мае. Кажется, что все среды отсутствуют.

Третья проблема заключается в том, что вы используете array_diff на двух массивах, один из которых содержит даты и другие, содержащие строки. Из документации:

Два элемента считаются равными, если и только если (строка) $ elem1 === (строка) $ elem2. В словах: когда строковое представление одно и то же.

В вашей $hdsarray вы используете "1-05-2015", чтобы обозначить первый день месяца, в то время как:

echo date('d-m-Y', strtotime("1-05-2015")); 

приводит "01-05-2015". Вам нужно будет добавить дополнительный 0 в $hdsarray для этих дат или работать с датами.

И последнее, но не менее важное: текущий алгоритм не будет работать правильно, если $hdsarray содержит даты для субботы или воскресенья, результат array_diff будет содержать эти даты. Поскольку вы хотите отфильтровать результат daterange, функция array_filter может быть более подходящей.

0

Несмотря на ответ уже предусмотрено, вот небольшой отрывок с классом обработки все для вас:

<?php 

class dateRange { 
    protected $start, $end, $daysToExclude, $datesToExclude; 

    function __construct($dateStart, $dateEnd, $daysToExclude, $datesToExclude) { 
     $this->start   = $dateStart; 
     $this->end    = $dateEnd; 
     $this->daysToExclude = $daysToExclude; 
     $this->datesToExclude = $this->fixFormat($datesToExclude); 
    } 

    public function getRangeLength ($callback = null) { 
     $tmp = array(); 

     $now = strtotime($this->start); 
     $to  = strtotime($this->end); 

     while ($now <= $to) { 
      if (!in_array(date("w", $now), $this->daysToExclude)) { 
       $tmp[] = date('d-m-Y', $now); 
      } 
      $now = strtotime('+1 day', $now); 
     } 

     is_callable($callback) && call_user_func($callback, array_diff($tmp,$this->datesToExclude)); 

     return count(array_diff($tmp,$this->datesToExclude)); 
    } 

    private function fixFormat($el) { 
     if (!is_array($el)) { 
      return false; 
     } 
     else { 
      foreach ($el as &$value) { 
       $value = date("d-m-Y",strtotime($value)); 
      } 
      return $el; 
     } 
    } 
} 

?> 

я решил сохранить текущую логику (используя date_diff), но я подумал, что, в в будущем у вас может быть ваш босс, говорящий вам: «Знаете, что? Я не хочу иметь понедельники, а там», поэтому в текущей системе вам придется вручную редактировать свою функцию и, возможно, вы не будете помнить больше того, что вы сделали.

Класс выше ожидает, что четыре параметра:

  • dateStart (ДМГ формат)
  • dateEnd (ДМГ формат)
  • daysToExclude (массив с идентификаторами дней, чтобы исключить -> например, массив (0, 6) исключить субботу и воскресенье).
  • dateToExclude (массив с датами для исключения, каждый поддерживаемый формат).

Класс автоматически исправит датыВыберите формат массива, чтобы вы могли использовать date_diff.

Ниже приведен пример, чтобы использовать его, следуя вашему делу:

<?php 

    $dateStart  = "01-05-2015"; 
    $dateEnd  = "01-06-2015"; 
    $daysToExclude = array(0,6); 
    $exclusions = array(
       "1-05-2015", 
       "2-05-2015", 
       "4-05-2015", 
       "5-05-2015", 
       "7-05-2015", 
       "8-05-2015", 
       "9-05-2015", 
       "11-05-2015", 
       "12-05-2015", 
       "14-05-2015", 
       "15-05-2015", 
       "16-05-2015", 
       "18-05-2015", 
       "19-05-2015", 
       "21-05-2015", 
       "22-05-2015", 
       "23-05-2015", 
       "25-05-2015", 
       "26-05-2015", 
       "28-05-2015", 
       "29-05-2015", 
       "30-05-2015" 
      ); 
      $dateRange = new dateRange($dateStart, $dateEnd, $daysToExclude, $exclusions); 
      echo $dateRange->getRangeLength(); 
?> 

Код выше выходов 5.

Функция getRangeLength также принимает обратный вызов и возвращает array в результате операции date_diff , так что вы можете также:

$dateRange->getRangeLength(function($res) { 
    echo "Literal output: <br />"; 
    print_r($res); 
    echo "<br />count is: " . count($res); 
}); 

Приведенные выше результаты:

Literal output: 
Array ([3] => 06-05-2015 [8] => 13-05-2015 [13] => 20-05-2015 [18] => 27-05-2015 [21] => 01-06-2015) 
count is: 5 

Так что, если вы впоследствии нужны будете удалить понедельники тоже, вы сможете легко сделать это путем изменения daysToExclude к array(0,1,6);

Надеются, что это будет полезно для всех, кто будет нуждаться в этом, несмотря на действительный ответ уже опубликован.

Ваша оригинальная проблема, в любом случае, была в значительной степени связана с функцией array_diff, которая НЕ выполняла свою работу из-за того, что строки даты были несовместимы, поскольку «1-01-2015» отличается от «01-01-2015», если вы сначала не конвертируете их по времени, а затем обратно в даты.

Смежные вопросы