SitePoint Sponsor

User Tag List

Results 1 to 16 of 16
  1. #1
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Working Days problem

    Hi,
    I am trying figure out if a day give is a working day(mon to friday). Actually What I am trying to do is that I am trying to go forward by X days, check if it is a working day , if it is not then I try to get next nearest working day.

    PHP Code:
    <?php

    echo getWorkingDate(12);

    function 
    getWorkingDate($daysInAdvance){
        
    $today=date('d-m-Y');
        
    $currentTime=strtotime("+$daysInAdvance days",  strtotime($today));
        
    $currentDate=date('Y-m-d',$currentTime);
        
    $currentDay=date('w',$currentTime);
        if (
    $daysInAdvance>7){
            
    $daysFWD=intval($daysInAdvance)/7.0;
            
    $currentTime=strtotime("+".intval($daysFWD*2)."days",  $currentTime);
            
    $currentDate=date('Y-m-d',$currentTime);
            
    $currentDay=date('w',$currentTime);
        }
        if (
    date('w',$currentTime)<=date('w',strtotime($today))){
            
    $currentTime=strtotime('+2 days',$currentTime);
            
    $currentDate=date('Y-m-d',$currentTime);
            
    $currentDay=date('w',$currentTime);
        }
        while(
    $currentDay==|| $currentDay==6){
            
    $currentTime=strtotime("+ 1 day"$currentTime);
            
    $currentDate=date('Y-m-d',$currentTime);
            
    $currentDay=date('w',$currentTime);
        }
        return 
    date('dmY',$currentTime);
    }
    ?>
    As you can see there is when function getWorkingDate is called it outputs a date. It seems to work well till 10 days in advance. As soon I pass 11 as an argument, it gives a which is too ahead (3 days) in time, and if I pass 12 as argument , it gives a day behind.

    Is it PHP bug, or fault in my codin?

  2. #2
    SitePoint Evangelist
    Join Date
    Jun 2006
    Location
    Wigan, Lancashire. UK
    Posts
    523
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What is this statement trying to do?
    PHP Code:
    $daysFWD=intval($daysInAdvance)/7.0;
    $currentTime=strtotime("+".intval($daysFWD*2)."days",  $currentTime); 
    because it's confusing me what you're trying to do here.

    Surely $daysInAdvance should be an integer anyway, but then you're dividing it by 7 which will give you a float, which you're then doubling and converting to an integer for the strtotime calculation.

    So +8 days will give 1.14285714 * 2 = 2.285714, which will add 2 days;
    +9 days will give 1.285714 * 2 = 2.5714287, which will add 2 days;
    +10 days will give 1.42857 * 2 = 2.85714, which will add 2 days;
    +11 days will give 1.5714287 * 2 = 3.142857, which will add 3 days
    ---
    Development Projects:
    PHPExcel
    PHPPowerPoint

  3. #3
    SitePoint Wizard silver trophybronze trophy Cups's Avatar
    Join Date
    Oct 2006
    Location
    France, deep rural.
    Posts
    6,869
    Mentioned
    17 Post(s)
    Tagged
    1 Thread(s)
    Yeah, I found that too confusing, this simply echos the next working day number.

    PHP Code:
    function getDow$tgt ){

    $dow date( ('w'), ( time() + ($tgt 86400) ) ) ;

     if( 
    $dow == || $dow == ) {

     
    // It is weekend, so adding 1 day 
     
    return getDow(++$tgt);

     }

    echo 
    '<p><b>' $dow '</b></p>';
    }

    // test array of next 20 days from today
    $days range020 );
    foreach( 
    $days as $v ){
    getDow$v );

    So as today is weds so it will output:

    3
    4
    5
    1
    1
    1
    2
    3
    4
    5
    1
    1
    1
    etc

  4. #4
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mark Baker View Post
    What is this statement trying to do?
    PHP Code:
    $daysFWD=intval($daysInAdvance)/7.0;
    $currentTime=strtotime("+".intval($daysFWD*2)."days",  $currentTime); 
    because it's confusing me what you're trying to do here.

    Surely $daysInAdvance should be an integer anyway, but then you're dividing it by 7 which will give you a float, which you're then doubling and converting to an integer for the strtotime calculation.

    So +8 days will give 1.14285714 * 2 = 2.285714, which will add 2 days;
    +9 days will give 1.285714 * 2 = 2.5714287, which will add 2 days;
    +10 days will give 1.42857 * 2 = 2.85714, which will add 2 days;
    +11 days will give 1.5714287 * 2 = 3.142857, which will add 3 days
    Oh Thanks for a quick reply. Well The idea was that to add weekends days.
    I was trying to take advantage of the int float conversion.I deleibretely added '.0' in front of 7. Forgive my bad variable names. I was frustrated. lol. But I found (My invension ,yes!!) a reasonably good solution to the problem:
    PHP Code:
    <?php

    echo getWorkingDate(1);

    function 
    getWorkingDate($daysInAdvance){
        
    $today=date('d-m-Y');
        
    $originalTime=strtotime("+$daysInAdvance days",  strtotime($today));
        
    $currentTime=$originalTime;
        while (
    date('w'$currentTime)==|| date('w'$currentTime)==6){
            
    $currentTime=strtotime("+1 days",  $currentTime);
        }
        
    $currentWeek=date('W'time());
        
    $weekInfuture=date('W'$currentTime);
        
    $daysToGoFWD=2*($weekInfuture-$currentWeek);
        
    $currentTime=strtotime("+$daysToGoFWD days",  $originalTime);
        while (
    date('w'$currentTime)==|| date('w'$currentTime)==6){
            
    $currentTime=strtotime("+1 days",  $currentTime);
        }
        return 
    date('dmY',$currentTime);
    }
    ?>
    The above solution have worked so far.But I prefer no more then 1 while loop.

  5. #5
    Web Professional
    Join Date
    Oct 2008
    Location
    London
    Posts
    862
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    function getNextWorkingDay($advance 0)
    {
        while (
    in_array(date('w'strtotime('+' $advance ' days')), array(0,6))) {
            
    $advance++;
        }
        
        return 
    strtotime('+' $advance ' days');
    }

    echo 
    date('r'getNextWorkingDay(4)); 

  6. #6
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks. I just want to know one more thing what does & means in following context:
    $someVariable=& someClass();

    Regards

  7. #7
    Web Professional
    Join Date
    Oct 2008
    Location
    London
    Posts
    862
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's invalid because you can't call a class. PHP will think that someClass() is a function and if it doesn't find it then it will throw a fatal error. Hard to say what it's supposed to do without context and valid code.

  8. #8
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    The & sign means you are 'passing by reference', a quick Google should point you in the right direction.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  9. #9
    Web Professional
    Join Date
    Oct 2008
    Location
    London
    Posts
    862
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    The & sign means you are 'passing by reference', a quick Google should point you in the right direction.
    In this particular case it's actually returning by reference. Well, it would be if the code was valid

  10. #10
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by decowski View Post
    PHP Code:
    function getNextWorkingDay($advance 0)
    {
        while (
    in_array(date('w'strtotime('+' $advance ' days')), array(0,6))) {
            
    $advance++;
        }
        
        return 
    strtotime('+' $advance ' days');
    }

    echo 
    date('r'getNextWorkingDay(4)); 
    I am sorry to bring this up again, but the code is not tested properly. I would agree that code is well written but its buggy. So what's the bug.
    Today is 25th of feb. I decided to run the code with arguments 3, and 4.The result was 2nd march 2009 for both of them.

    I think code is checking if the day is weekend or not, if its a weekend, we increment. However if it is not a weekend and code does not compensate for any weekend in middle. What I mean here is if there is one weekend between today and next working day, than date should increment by 2, and if there 2 weekend falling than date should increment by 4.

    You may look at the my post number 4 of this thread which is correct code, but when there is change in year even it start to act funny.
    Last edited by uniqueumang; Feb 24, 2009 at 17:57. Reason: More referencing

  11. #11
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Today being feb 25th really depends on what time zone you are in. The time zone of the computer where this code executes may also be different. Why don't you take a look.

  12. #12
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by crmalibu View Post
    Today being feb 25th really depends on what time zone you are in. The time zone of the computer where this code executes may also be different. Why don't you take a look.
    Thanks genius. I know that. I gave it as an example.

    you can take any date, for example IF today is 25th of feb 2009, and IF you try to do the following :
    PHP Code:
    /*today is 25th of feb 2009*/
    echo date('d-m-Y'getNextWorkingDay(3)); //Three Working days .prints out 02-03-2009 expected 02-03-2009
    echo date('d-m-Y'getNextWorkingDay(4)); //Four Working Days.prints out 02-03-2009 expected 03-03-2009
    echo date('d-m-Y'getNextWorkingDay(5)); //Five Working Days.prints out 02-03-2009 expected 04-03-2009 
    As you can see the difference between expected value and actual value, hence the point I am trying to make is the code only check if day in advance is a weekend or not, if it is then incrememnt by one until day isn't a weekend.

  13. #13
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No need to get snippy. You're here asking for help, and you're claiming a bug when you never made your desired functionality very clear until now.

    Quote Originally Posted by uniqueumang View Post
    Hi,
    I am trying figure out if a day give is a working day(mon to friday). Actually What I am trying to do is that I am trying to go forward by X days, check if it is a working day , if it is not then I try to get next nearest working day.
    Quote Originally Posted by uniqueumang View Post
    I think code is checking if the day is weekend or not, if its a weekend, we increment. However if it is not a weekend and code does not compensate for any weekend in middle. What I mean here is if there is one weekend between today and next working day, than date should increment by 2, and if there 2 weekend falling than date should increment by 4.

    You may look at the my post number 4 of this thread which is correct code, but when there is change in year even it start to act funny.

  14. #14
    SitePoint Addict
    Join Date
    Aug 2005
    Posts
    207
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You don't need a loop...

    PHP Code:

    <?php

    function getDay $days )
    {
         list ( 
    $month$day$year$number ) = explode ' 'date 'm d Y N'strtotime '+' $days 'day' ) ) );

        if ( 
    $number )
        {
            
    $days += $number;

             list ( 
    $month$day$year ) = explode ' 'date 'm d Y'strtotime '+' $days 'day' ) ) );
        }

        return 
    $month '/' $day '/' $year;
    }

    echo 
    getDay );

    ?>

  15. #15
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by crmalibu View Post
    No need to get snippy. You're here asking for help, and you're claiming a bug when you never made your desired functionality very clear until now.
    Sorry for that. What is the time zone got to do with the code. It will respond same in all time zone. Agreed the problem definition was not clear enough.

    However , code provided by decowski(post #5) was in response to my function (post #4).

    I have found the solution , and upload correct solution soon. However I am looking a solution with min number of while loops.

  16. #16
    SitePoint Enthusiast
    Join Date
    Nov 2007
    Posts
    63
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    function getWorkingDate($daysInAdvance){
            
    $today=date('d-m-Y');
            
    $originalTime=strtotime("+$daysInAdvance days",  strtotime($today));
            
    $currentTime=$originalTime;
            while (
    date('w'$currentTime)==|| date('w'$currentTime)==6){
                
    $currentTime=strtotime("+1 days",  $currentTime);
            }
            
    $currentWeek=date('W'time());
            
    $currentYear=date('Y'time());
            
    $weekInfuture=date('W'$currentTime);
            
    $yearInfuture=date('Y'$currentTime);
            if((
    $yearInfuture-$currentYear)==0){
                if (
    $weekInfuture>$currentWeek)
                    
    $daysToGoFWD=2*($weekInfuture-$currentWeek);
                else 
                    
    $daysToGoFWD=2*((date('W'strtotime(date('24-12-'.$currentYear)))+1)-$currentWeek);
            }else {
                
    $enofTheYear=date('W'strtotime(date('31-12-'.$currentYear)))=='01'?date('W'strtotime(date('24-12-'.$currentYear))):date('W'strtotime(date('31-12-'.$currentYear)));
                
    $startoftheYear=date('W'strtotime(date('1-1-'.$yearInfuture)))=='01'?01:date('W'strtotime(date('7-1-'.$yearInfuture)));
                
    $daysToGoFWD=2*(($weekInfuture-$startoftheYear)+($enofTheYear-$currentWeek)+2);
            }
            
    $currentTime=strtotime("+$daysToGoFWD days",  $originalTime);
            while (
    date('w'$currentTime)==|| date('w'$currentTime)==6){
                
    $currentTime=strtotime("+1 days",  $currentTime);
            }
            return 
    date('Y-m-d',$currentTime);
        } 
    Ok this seem to be a correct solution to the problem.Howver I am still looking optimized simplar solution.Please do post your ideas


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •