PHP天差计算错误

时间:2015-06-09 08:25:13

标签: php date php-5.3

我有一些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;

4 个答案:

答案 0 :(得分:3)

我能看到的唯一问题是使用array_diff,它实际上包括被dateRange函数排除的sat和sun,如果在假期列表中找不到的话。

相反,您可以在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);
    }
    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个日期都在结果中,不是坐着,太阳,也不在假期列表中。

答案 1 :(得分:0)

这里似乎有几个问题。首先,正如其他人所指出的那样:

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

仅检查星期日,如果它还应包括星期六,它应该是:

$hdsarray

其次,似乎$hdsarray数组不包含5月的所有日期。似乎所有星期三都不见了。

第三个问题是你在两个数组上使用array_diff,一个包含Dates,另一个包含字符串。来自文档:

  

当且仅当(字符串)$ elem1 ===时,才认为两个元素相等   (字符串)$ elem2。用文字表示:当字符串表示相同时。

"1-05-2015"您使用 echo date('d-m-Y', strtotime("1-05-2015")); 表示该月的第一天,同时:

"01-05-2015"

结果为0。您需要在$hdsarray中为这些日期添加额外的$hdsarray,或者也可以使用日期。

最后但并非最不重要的是,如果array_diff包含星期六或星期日的日期,则当前算法将无法正常运行,daterange的结果仍将包含这些日期。由于您要过滤select * from Customer c join Email e on e.cust_id = c.id 的结果,array_filter函数可能更合适。

答案 2 :(得分: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),但我认为,将来你可能让老板告诉你&34;你知道吗?我也不想在星期一和星期一一起玩#34;因此,使用当前系统,您必须手动编辑您的功能,或许,您将不再记得您所做的事情。

上面的课程需要四个参数:

  • dateStart(d-m-Y格式)
  • dateEnd(d-m-Y格式)
  • daysToExclude(包含要排除的天数的ID的数组 - &gt;示例数组(0,6)以排除星期六和星期日)。
  • datesToExclude(包含要排除的日期的数组,支持的每种格式)。

该类将自动修复datesToExclude数组格式,以便您使用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也接受回调并返回date_diff操作产生的array,所以你也可以:

$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函数有很大关系,因为日期字符串不兼容,因此不能正常工作,因为&#34; 1-01 -2015&#34;与&#34; 01-01-2015&#34;不同,除非您先将它们中的两个转换为时间然后再转换为日期。

答案 3 :(得分:0)

代码很好(除了根本不使用$now之外)。问题是$hdsarray是错误的:

它应该$hdsarray = array("01-05-2015", "02-05-2015", "04-05-2015", "05-05-2015", "07-05-2015", "08-05-2015", "09-05-2015",...);

date('d-m-Y', $current);将在1到9之间的所有日期始终返回前导0。

这就是差异的来源。