如果日期范围包含PHP列表中的日期,则减去天数

时间:2022-08-25 18:51:06

I have a calculation that gives the total amount of laboral days between 2 dates. However, if the range of dates contains any date present in a list (holidays), I must subtract each day from holidays from the total amount of days.

我有一个计算,给出了两个日期之间的实验日总数。但是,如果日期范围包含列表中的任何日期(假期),我必须从总天数中减去假期中的每一天。

It means if in the list of holidays i have the 25-03-2016, and the range of dates go from 21-03-2016 to 25-03-2016, it should count only 4 days, not 5.

这意味着如果在假期列表中我有25-03-2016,日期范围从2016年3月21日到2016年3月25日,它应该只计算4天,而不是5天。

At the moment, I have this table of holidays in the DB:

目前,我在DB中有这个假期表:

Date
01-01-2016
25-03-2016
27-06-2016
16-07-2016
15-08-2016
19-09-2016
10-10-2016
31-10-2016
01-11-2016
08-12-2016

And the total amount of laboral days comes from this function:

实验日的总量来自这个功能:

$days=0;
$aux=strtotime($begin_date); #Aux for days
while ($aux <=strtotime($end_date)) { #While the Aux is less than the end, I verify wich day of the week is this
    $auxday=date('N',$aux);
    if ($auxday!='6'&&$auxday!='7') { # if is different of 6 or 7, (saturday and sunday) I add 1 to the total amount of days
        $days++;
    }
    $aux=$aux+86400; #I add 1 day to AUX
}

Update

    $sqlF="SELECT * FROM tbl000_feriados";
    $requestF=mysqli_query($connect,$sqlF);
    $holidays=mysqli_fetch_array($requestF);
    foreach($holidays as $arr){
    $holiday_arr[] = strtotime($arr);
    }
    $days=0;
    $aux=strtotime($begin_date);
    while ($aux <=strtotime($end_date)) { 
    if(!in_array($aux,$holiday_arr)){
    $auxday=date('N',$aux);
    if ($auxday!='6'&&$auxday!='7') { 
    $days++;
    }
    }
    $aux=$aux+86400; 
}

It do not subtract the days of the holidays

它不会减去假期的日子

**** UPADTE 2

**** UPADTE 2

The problem is related with the lecture from the table tbl000_feriados, because if i put the data manually into the array

问题与表tbl000_feriados中的讲座有关,因为如果我将数据手动放入数组中

 array(2016-03-25)

for instance, it makes the subtract correctly.

例如,它正确地减去。

something is going wrong about reading the date from tbl000_feriados

从tbl000_feriados读取日期出了点问题

$sqlF="SELECT * FROM tbl000_feriados";
$requestF=mysqli_query($connect,$sqlF);
$holidays=mysqli_fetch_array($requestF);

***** UPDATE 3

*****更新3

For some reason, it make an aditional discount when im counting days from 23/03 and avobe 28/03

出于某种原因,当我计算从23/03和avobe 28/03开始计算的天数时,它会提供额外的折扣

3 个解决方案

#1


0  

First, make an array of the dates in holiday list by converting them into strtotime format.

首先,通过将日期转换为strtotime格式,在假日列表中创建日期数组。

$days=0;
$holidays = array('2016-01-01', '2016-03-25');
foreach($holidays as $arr){
  $holiday_arr[] = strtotime($arr);
}
$begin_date = '2016-01-01';
$end_date = '2017-01-01';
$aux=strtotime($begin_date); #Aux for days
while ($aux <=strtotime($end_date)) { 

then compare it with the new array, if this date not exists in holiday list array then, proceed from here

然后将它与新数组进行比较,如果假日列表数组中不存在此日期,则从此处继续

if(!in_array($aux,$holiday_arr)){

While the Aux is less than the end, I verify wich day of the week is this

虽然Aux不到最后,但我确认星期几是这个

    $auxday=date('N',$aux);
    if ($auxday!='6'&&$auxday!='7') { # if is different of 6 or 7, (saturday and sunday) I add 1 to the total amount of days
        $days++;
}
    }
    $aux=$aux+86400; #I add 1 day to AUX
}

#2


1  

You might be able to find the number of holidays which fall between given dates ( $begin_date and $end_date in your case) with the mysql BETWEEN operator:

您可以使用mysql BETWEEN运算符找到在给定日期(在您的情况下为$ begin_date和$ end_date)之间的假期数:

SELECT COUNT(*) from holidays where Date between Date('2016-02-05') and date('2016-04-01');

As long as the Date in your databse is a date or datetime type in the database, mysql will know how to process it. Note however that your european date format (dd-mm-yyyy) , while arguably more logical than the goofy US mm-dd-yyyy format, may not properly test as a date. I highly recommend the more universally consistent YYYY-MM-DD format ( which has the additional benefit that chronological order matches lexicographical order, which means an alphabetized date list will also be in chronoligical order! )

只要数据库中的Date是数据库中的日期或日期时间类型,mysql就会知道如何处理它。但请注意,您的欧洲日期格式(dd-mm-yyyy)虽然可能比愚蠢的美国mm-dd-yyyy格式更合乎逻辑,但可能无法正确测试日期。我强烈推荐更普遍一致的YYYY-MM-DD格式(它具有按时间顺序与字典顺序相匹配的额外好处,这意味着按字母顺序排列的日期列表也将按时间顺序排列!)

Keeping dates as dates in the database is one of the smartest things you can do. Not only are you able to make date-centric comparisons like this, but you'll also be in good shape to start thinking about supporting - or at least explicitly setting - timezones. I caution all developers of date-related programs to start with explicit timezones. If you put dates into your table but don't apply the correct timezone, it can be hard to clean up when you try to handle timezones later and the data wasn't put in as the timezone the mysql server ran in by default. Icky!

将日期保留为数据库中的日期是您可以做的最明智的事情之一。您不仅可以进行这样的以日期为中心的比较,而且您也可以开始考虑支持 - 或者至少明确设置 - 时区。我提醒日期相关程序的所有开发人员都要使用显式时区。如果您将日期放入表中但没有应用正确的时区,那么当您稍后尝试处理时区并且数据未作为mysql服务器默认运行的时区放入时,可能很难清理。恶心!

#3


0  

Try the following:

请尝试以下方法:

$holidays = array('2016-01-01', '2016-03-25');

$begin_date = new DateTime('2016-01-01');
$end_date = new DateTime('2017-01-01');
$exclude = 0;

// Loop over holidays to find out whether they are in the range
foreach ($holidays as $holiday) {
    if (isWithinDates(new DateTime($holiday), $begin_date, $end_date)) {
        $exclude++;
    }
}

function isWithinDates(DateTime $date, DateTime $start, DateTime $end)
{
    return $date >= $start && $date <= $end;
}

// Get the amount of days between our start date and the end date
// and subtract the amount of days that we know to be holidays
$interval = $begin_date->diff($end_date)->days - $exclude;

var_dump($interval);

#1


0  

First, make an array of the dates in holiday list by converting them into strtotime format.

首先,通过将日期转换为strtotime格式,在假日列表中创建日期数组。

$days=0;
$holidays = array('2016-01-01', '2016-03-25');
foreach($holidays as $arr){
  $holiday_arr[] = strtotime($arr);
}
$begin_date = '2016-01-01';
$end_date = '2017-01-01';
$aux=strtotime($begin_date); #Aux for days
while ($aux <=strtotime($end_date)) { 

then compare it with the new array, if this date not exists in holiday list array then, proceed from here

然后将它与新数组进行比较,如果假日列表数组中不存在此日期,则从此处继续

if(!in_array($aux,$holiday_arr)){

While the Aux is less than the end, I verify wich day of the week is this

虽然Aux不到最后,但我确认星期几是这个

    $auxday=date('N',$aux);
    if ($auxday!='6'&&$auxday!='7') { # if is different of 6 or 7, (saturday and sunday) I add 1 to the total amount of days
        $days++;
}
    }
    $aux=$aux+86400; #I add 1 day to AUX
}

#2


1  

You might be able to find the number of holidays which fall between given dates ( $begin_date and $end_date in your case) with the mysql BETWEEN operator:

您可以使用mysql BETWEEN运算符找到在给定日期(在您的情况下为$ begin_date和$ end_date)之间的假期数:

SELECT COUNT(*) from holidays where Date between Date('2016-02-05') and date('2016-04-01');

As long as the Date in your databse is a date or datetime type in the database, mysql will know how to process it. Note however that your european date format (dd-mm-yyyy) , while arguably more logical than the goofy US mm-dd-yyyy format, may not properly test as a date. I highly recommend the more universally consistent YYYY-MM-DD format ( which has the additional benefit that chronological order matches lexicographical order, which means an alphabetized date list will also be in chronoligical order! )

只要数据库中的Date是数据库中的日期或日期时间类型,mysql就会知道如何处理它。但请注意,您的欧洲日期格式(dd-mm-yyyy)虽然可能比愚蠢的美国mm-dd-yyyy格式更合乎逻辑,但可能无法正确测试日期。我强烈推荐更普遍一致的YYYY-MM-DD格式(它具有按时间顺序与字典顺序相匹配的额外好处,这意味着按字母顺序排列的日期列表也将按时间顺序排列!)

Keeping dates as dates in the database is one of the smartest things you can do. Not only are you able to make date-centric comparisons like this, but you'll also be in good shape to start thinking about supporting - or at least explicitly setting - timezones. I caution all developers of date-related programs to start with explicit timezones. If you put dates into your table but don't apply the correct timezone, it can be hard to clean up when you try to handle timezones later and the data wasn't put in as the timezone the mysql server ran in by default. Icky!

将日期保留为数据库中的日期是您可以做的最明智的事情之一。您不仅可以进行这样的以日期为中心的比较,而且您也可以开始考虑支持 - 或者至少明确设置 - 时区。我提醒日期相关程序的所有开发人员都要使用显式时区。如果您将日期放入表中但没有应用正确的时区,那么当您稍后尝试处理时区并且数据未作为mysql服务器默认运行的时区放入时,可能很难清理。恶心!

#3


0  

Try the following:

请尝试以下方法:

$holidays = array('2016-01-01', '2016-03-25');

$begin_date = new DateTime('2016-01-01');
$end_date = new DateTime('2017-01-01');
$exclude = 0;

// Loop over holidays to find out whether they are in the range
foreach ($holidays as $holiday) {
    if (isWithinDates(new DateTime($holiday), $begin_date, $end_date)) {
        $exclude++;
    }
}

function isWithinDates(DateTime $date, DateTime $start, DateTime $end)
{
    return $date >= $start && $date <= $end;
}

// Get the amount of days between our start date and the end date
// and subtract the amount of days that we know to be holidays
$interval = $begin_date->diff($end_date)->days - $exclude;

var_dump($interval);