Day difference without weekends

2019-01-04 10:53发布

I want to count the total day difference from user input

For example when the user inputs

start_date = 2012-09-06 and end-date = 2012-09-11

For now I am using this code to find the diffeence

$count = abs(strtotime($start_date) - strtotime($end_date));
$day   = $count+86400;
$total = floor($day/(60*60*24));

The result of total will be 6. But the problem is that I dont want to include the days at weekend (Saturday and Sunday)

2012-09-06
2012-09-07
2012-09-08 Saturday
2012-09-09 Sunday
2012-09-10
2012-09-11

So the result will be 4

----update---

I have a table that contains date,the table name is holiday date

for example the table contains 2012-09-07

So, the total day will be 3, because it didn't count the holiday date

how do I do that to equate the date from input to date in table?

9条回答
Fickle 薄情
2楼-- · 2019-01-04 11:11

If you don't need full days but accurate seconds instead try this code. This accepts unix timestamps as an input.

function timeDifferenceWithoutWeekends($from, $to) {
    $start = new DateTime("@".$from);
    $current = clone $start;
    $end = new DateTime("@".$to);
    $sum = 0;
    while ($current<$end) {
        $endSlice = clone $current;
        $endSlice->setTime(0,0,0);
        $endSlice->modify('+1 day');
        if ($endSlice>$end) {
            $endSlice= clone $end;
        }
        $seconds = $endSlice->getTimestamp()-$current->getTimestamp();
        $currentDay = $current->format("D");
        if ($currentDay != 'Sat' && $currentDay != 'Sun') {
            $sum+=$seconds;
        }
        $current = $endSlice;
    }
    return $sum;
}
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-04 11:12

Here's an alternative to calculate business days between two dates and also excludes USA holidays using Pear's Date_Holidays from http://pear.php.net/package/Date_Holidays.

$start_date and $end_date should be DateTime objects (you can use new DateTime('@'.$timestamp) to convert from timestamp to DateTime object).

<?php
function business_days($start_date, $end_date)
{
  require_once 'Date/Holidays.php';
  $dholidays = &Date_Holidays::factory('USA');
  $days = 0;

  $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

  foreach($period as $dt)
  {
    $curr = $dt->format('D');

    if($curr != 'Sat' && $curr != 'Sun' && !$dholidays->isHoliday($dt->format('Y-m-d')))
    {
      $days++;
    }
  }
  return $days;
}
?>
查看更多
叛逆
4楼-- · 2019-01-04 11:13

Very easy with my favourites: DateTime, DateInterval and DatePeriod

$start = new DateTime('2012-09-06');
$end = new DateTime('2012-09-11');
// otherwise the  end date is excluded (bug?)
$end->modify('+1 day');

$interval = $end->diff($start);

// total days
$days = $interval->days;

// create an iterateable period of date (P1D equates to 1 day)
$period = new DatePeriod($start, new DateInterval('P1D'), $end);

// best stored as array, so you can add more than one
$holidays = array('2012-09-07');

foreach($period as $dt) {
    $curr = $dt->format('D');

    // substract if Saturday or Sunday
    if ($curr == 'Sat' || $curr == 'Sun') {
        $days--;
    }

    // (optional) for the updated question
    elseif (in_array($dt->format('Y-m-d'), $holidays)) {
        $days--;
    }
}


echo $days; // 4
查看更多
对你真心纯属浪费
5楼-- · 2019-01-04 11:21

date('N') gets the day of the week (1 - Monday, 7 - Sunday)

$start = strtotime('2012-08-06');
$end = strtotime('2012-09-06');

$count = 0;

while(date('Y-m-d', $start) < date('Y-m-d', $end)){
  $count += date('N', $start) < 6 ? 1 : 0;
  $start = strtotime("+1 day", $start);
}

echo $count;
查看更多
兄弟一词,经得起流年.
6楼-- · 2019-01-04 11:23

The easiest and fastest way to get difference without weekends is by using Carbon library.

Here's an example how to use it:

<?php

$from = Carbon\Carbon::parse('2016-05-21 22:00:00');
$to = Carbon\Carbon::parse('2016-05-21 22:00:00');
echo $to->diffInWeekdays($from);
查看更多
Summer. ? 凉城
7楼-- · 2019-01-04 11:25

In my case I needed the same answer as OP, but wanted something a little smaller. @Bojan's answer worked, but I didn't like that it doesn't work with DateTime objects, required using timestamps, and was comparing against strings instead of the actual objects themselves (which feels hacky)... Here's a revised version of his answer.

function getWeekdayDifference(\DateTime $startDate, \DateTime $endDate)
{
    $days = 0;

    while($startDate->diff($endDate)->days > 0) {
        $days += $startDate->format('N') < 6 ? 1 : 0;
        $startDate = $startDate->add(new \DateInterval("P1D"));
    }

    return $days;
}

Per @xzdead's comment if you'd like this to be inclusive of the start and end date:

function getWeekdayDifference(\DateTime $startDate, \DateTime $endDate)
{
    $isWeekday = function (\DateTime $date) {
        return $date->format('N') < 6;
    };

    $days = $isWeekday($endDate) ? 1 : 0;

    while($startDate->diff($endDate)->days > 0) {
        $days += $isWeekday($startDate) ? 1 : 0;
        $startDate = $startDate->add(new \DateInterval("P1D"));
    }

    return $days;
}
查看更多
登录 后发表回答