tags:

views:

640

answers:

5

The title is pretty much self explanatory. Given two dates what is the best way of finding the number of week days using PHP? Week days being Monday to Friday.

For instance, how would I find out that there are 10 week days in between 31/08/2008 and 13/09/2008?

A: 

One way would be to convert the dates to unix timestamps using strtotime(...), subtracting the results and div'ing with 86400 (24*60*60):

$dif_in_seconds = abs(strtotime($a) - strtotime($b));
$daysbetween = $dif_in_seconds / 86400;

ETA: Oh.. You meant weekdays as in Mon-Fri.. Didn't see that at first..

erlando
That would introduce all the problems that come with unix timestamps. What happens if you have a pre-1970 date?
docgnome
The solution is perfectly viable given certain problem domains. But of course you're right in principle. Though I suspect that for the majority of programs written today you wouldn't worry about workday-differences in dateranges pre-1970.
erlando
erlando, Probably not. I'm just a bit shy of unix timestamps and avoid them like the plague these days, because I've seen what can happen when they are used to represent things they shouldn't. Like dates. Creates timezone issues. I think time is evil and we should just pretend it isn't there. :-p
docgnome
Time is indeed evil.. :-) I actually agree with you and all my persistent dates (ie in db's) are datetimes. But when you have "simple" calculations (no calculation on dates are simple..) timestamps may be the way to go.. :-)
erlando
A: 

The best way is to iterate through all dates in between the given date range, and get the day of week for each date. If it's a week day, increment a certain counter. At the end of the process you get the number of weekdays.

The PHP functions mktime() and date() (for working with UNIX timestamps) are your friends here.

cruizer
A: 

by the way I was delighted to find out that recent versions of PHP already have a DateTime object :) finally...

cruizer
+2  A: 
        $datefrom = strtotime($datefrom, 0);
        $dateto = strtotime($dateto, 0);

        $difference = $dateto - $datefrom;

        $days_difference = floor($difference / 86400);
        $weeks_difference = floor($days_difference / 7); // Complete weeks

        $first_day = date("w", $datefrom);
        $days_remainder = floor($days_difference % 7);

        $odd_days = $first_day + $days_remainder; // Do we have a Saturday or Sunday in the remainder?
        if ($odd_days > 7) { // Sunday
            $days_remainder--;
        }
        if ($odd_days > 6) { // Saturday
            $days_remainder--;
        }

        $datediff = ($weeks_difference * 5) + $days_remainder;

From here: http://www.addedbytes.com/php/php-datediff-function/

kobusb
+1  A: 

If you are creating an invoicing system, you have to think about the bank holidays, Easter, etc. It is not simple to compute it.

The best solution I have ever seen is to pregenerate a table with days and its type to SQL database (row per day = 365 rows per year) and then perform simple count query with proper selection (WHERE clause).

You can find this solution fully described in Joe Celko's Thinking in Sets: Auxiliary, Temporal, and Virtual Tables in SQL

Matej
Wow, that is a rather unique solution to that problem. Not only is it update-able but it likely scales well too. Amazing. Kudos to whoever came up with that. I've seen countless methods and algorithms fail, but this sounds solid.
Abyss Knight