/    Sign up×
Community /Pin to ProfileBookmark

date after 14 working days

I have a script to count working days between 2 dates. Actually I need extra function to script count date when 14 working days will pass.

For example: start date will be “2010-04-18”, so I want to script count that after 14 working days it will be “2010-05-07”.

My code:

[code=php]
<?php
function workDays($date1, $date2, $withStartDay = false) {
$date1=strtotime($date1);
$date2=strtotime($date2);
if ($date2===$date1 && !$withStartDay) return 0;
$char=1;
if ($date1>$date2)
{$datePom=$date1;$date1=$date2;$date2=$datePom;$char=-1;}
$count=0;
if (!$withStartDay)
$date1=strtotime(‘+1 day’,$date1);
$date2=strtotime(‘+1 day’,$date2);
$lastYear = null;
$hol=array(’01-01′,’05-01′,’05-03′,’08-15′,’11-01′,’11-11′,’12-25′,’12-26′);
while ($date1<$date2) {
$year = date(‘Y’, $date1);
if ($year !== $lastYear){
$lastYear = $year;
$easter = date(‘m-d’, easter_date($year));
$date = strtotime($year . ‘-‘ . $easter);
$easterSec = date(‘m-d’, strtotime(‘+1 day’, $date));
$cc = date(‘m-d’, strtotime(‘+60 days’, $date));
$hol[8] = $easter;
$hol[9] = $easterSec;
$hol[10] = $cc;
}
$weekDay=date(‘w’,$date1);
if (!($weekDay==0 || $weekDay==6 || in_array(date(‘m-d’,$date1),$hol)))
$count++;
$date1=strtotime(‘+1 day’,$date1);
}
$count*=$char;
return $count;
}
?>
[/code]

Any help will be appreciated.

to post a comment
PHP

5 Comments(s)

Copy linkTweet thisAlerts:
@mavigozlerApr 18.2010 — Try:

[code=php]<?php

$startDate = new DateTime("yyyy-mm-dd"); // note date format...substitute your numbers here
$startDate->modify("+14 day");
$targetDate = $startDate->format("Y-m-d"); // the string is as it should be, returns a string in that format
?>[/code]




Please refer to the authoritative reference on the class and methods here:

[LIST]
  • [*]http://php.net/manual/en/ref.datetime.php

  • [*]http://www.php.net/manual/en/class.datetime.php

  • [/LIST]
    Copy linkTweet thisAlerts:
    @HelleshternauthorApr 18.2010 — No, that's not what I need. It just shows date after 14 days but I need after 14 work (bussiness) days.
    Copy linkTweet thisAlerts:
    @BIOSTALLApr 18.2010 — See this post:

    http://stackoverflow.com/questions/336127/calculate-business-days-in-php

    The function mentioned in post #2 sounds like what you are after and also deals with holidays.
    Copy linkTweet thisAlerts:
    @mavigozlerApr 19.2010 — Yes, you most certainly did say 14 [I][B]working[/B][/I] days in your original

    post.

    In tackling the problem, you need to decide what a "working day" is. Does that

    mean skipping holidays or just Saturdays and Sundays? And on whose

    cultural/national calendar?

    I got carried away coding some stuff. The code below is first-draft, thoroughly

    untested code. With perhaps a small amout of debugging, it can be made to work.

    I present it as showing the logic of computing what you want. There are 3 sections

    to this code.

  • 1. At the top are couple of variables. One is for specifying the offset of working

    days are you are interested in. Right now the code computes the forward offset,

    likely not the reverse, but with a line of code here and there, you can make it

    versatile.


  • Another important variable is the array of holidays. Its elements are strings

    that must be done in three different formats:

    i. "mm-dd": for holidays that always fall on a day and month of year, like

    the Fourth of July and Christmas Day

    ii. "X-ddd-mmm": X is a singler letter--"F" for first, "L" for last---or

    numeric--"1", "2", "3", "4" for first, second, etc. "ddd" is a three-letter

    abbreviation for the day of the week ("Sun", "Mon", etc). And "mmm" is

    the 3-letter abbreviation for a month ("Jan", "Feb", etc). This refers to

    holidays like Thanksgiving day, which is last Thursday of November: "L-Thu-Nov".

    iii. "X-ddd-ddd-mmm": this is for those holidays that have a more perverse

    algorithm like Labor, which is first Mon after first Tue of September,

    I believe: "F-Mon-Tue-Sep"

    The function getSpecialDay() is supposed to make use of the

  • 2. The functions and support functions:

    i. int getNumericDayOfWeek(string $dayOfWeekName)

    give it day of week name like "Fri" or "Friday" and it returns the

    numeric day of the week according to PHP (returns 5). Sun=0, Sat=6.

    called by isHoliday().


  • ii. boolean isWeekend($dateObj)

    param is a DateTime object whose date you have set/modified.

    the function returns boolean 'true' to tell you if the date is a Sat or Sun

    of false otherwise

    iii. boolean isHoliday($dateObj)

    param is a DateTime object whose date you have set/modified.

    function evaluates whether the set date is a holiday based on the

    values you put in the $holiday array. Returns 'true' if it find a match

    element in the array.

    iv. int getSpecialDay(string $dayType, int $dayOfWeek, string $month, string $year)

    a support function for isHoliday().

    $dayType can be "F", "L", "1", "2", "3", "4" generally. refers respectively

    to first, last, second, etc

    $dayOfWeek is a numeric for the day of week as PHP understands it (Sun=0, Sat=6)

    $month is a two-digit number for the month "01" = Jan, etc.

    $year is a four-digit number for the year.

    This function uses the month and year, finds the 1st, 2nd, last, day of week

    that you specify. It returns the day of the month that the special day falls

    on, as an int.

  • 3. The third section is global scope code that you can use for putting in

    your start days, and then it produces output to report the date X number

    of working days from now.


  • [code=php]<?php
    /* PHP does not have "date" type, so "mm-dd" strings are used
    some holidays are odd:

    Thanksgiving = last Thursday and Fridayof November: "L-Thu-Nov", "L-Fri-Nov"
    Labor Day = first Monday after first Tuesday in September: "F-Mon-Tue-Sep" */

    $workingDaysPeriod = 14;

    $holidays = array(
    "07-04", "12-25", "L-Thu-Nov", "L-Fri-Nov", "F-Mon-Tue-Sep"
    );
    function getNumericDayOfWeek($dayOfWeekName) {
    $daysOfWeekLongNames = array("Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday","Friday","Saturday"); // PHP day of week numeric order
    for ($i = 0; $i < count($daysOfWeekLongNames); $i++)
    if (strcasecmp($dayOfWeekName, $daysOfWeekNames[$i]) == 0 ||
    strcasecmp($dayOfWeekName, substr($daysOfWeekNames[$i], 0, 3)) == 0)
    return $i;
    return -1;
    }
    function isWeekend($dateObj) {
    $day = $dateObj->format('w');
    if ($day == "0" || $day == "6")
    return true;
    return false;
    }
    function isHoliday($dateObj) {
    foreach ($holidays as $element)
    if (preg_match("/(d{2})-(d{2})/", $element, $matches) > 0) {
    if ((int)$matches[0] == (int)$dateObj->format('m') &&
    (int)$matches[1] == (int)$dateObj->format('d'))
    return true;
    } else {
    preg_match("/(L|F)-(w{3})-(w{3})-(w{3})?/", $element, $matches) > 0)
    if (count($matches) > 3 && $dateObj->format('m') == $matches[3]) {
    $markerDayOfWeek = getNumericDayOfWeek($matches[2]);
    $markerDay = getSpecialDay($matches[0], $dayOfWeek, $matches[2],
    $dateObj->format("Y"));
    $targetDayOfWeek = getNumericDayOfWeek($matches[1]);
    if ($targetDayOfWeek < $markerDayOfWeek)
    $targetDayOfWeek + 7;
    $targetDay = $markerDay + $targetDayOfWeek - $markerDayOfWeek;
    if ($dateObj->format('d') == $targetDay)
    return true;
    } else if ($dateObj->format('m') == $matches[2]) {
    $dayOfWeek = getNumericDayOfWeek($matches[1]);
    if ($dateObj->format('d') ==
    getSpecialDay($matches[0], $dayOfWeek, $matches[1],
    $dateObj->format("Y")))
    return true;
    }
    }
    return false;
    }
    function getSpecialDay($dayType, $dayOfWeek, $month, $year) {
    /* return value: the date of the month and year that occurs for a special day
    of that month, such as first or last Wednesday, 2nd Thursday, etc. */
    /* $dayType can be "L" = last, "F" = first, "1" = first type of day of that month,
    "2" = second type of day of that month, etc */
    // $dayOfWeek integer type, range: 0 = Sun to 6 = Sat, the PHP date() convention
    /* error checking code on params not done:

    1. check type string having 4 numeric digits for $years,
    2. check type string having 2 numeric digits for $month */
    // get day of week of the first day of the target month and year
    $testDate = new DateTime("$year-$month-01");
    $testDayOfWeek = (int)$testDate->format('w');
    $testDay = 1;
    while ($dayOfWeek != $testDayOfWeek) {
    $testDayOfWeek++;
    $testDay++;
    if (($testDayOfWeek % 6) == 0)
    $testDayOfWeek = 0;
    }
    if ($dayType == "F" || $dayType == "1" || $dayType == 1)
    return $testDay;
    $daysInMonths = array(31,28,31,30,31,30,31,31,30,31,30,31);
    if ($testDate->format('L') == 1) // if specified year is leap year, set Feb
    array[1] = 29;
    if ($dayType == "L") {
    while ($testDay + 7 < $daysInMonths[(int)$month])
    $testDay += 7;
    return $testDay;
    }
    if (is_numeric($dayType) == true) {
    for ($week = 1; $week < (int)$dayType; $week++) {
    $testDay += 7;
    if ($testDay > $daysInMonths[(int)$month])
    return NULL;
    }
    return $testDay;
    }
    return NULL;
    }
    $testDate = new DateTime("yyyy-mm-dd");
    $workingDayCount = 0;
    do {
    $testDate->modify("+1 day");
    if (isWeekend($testDate) == false && isHoliday($testDate) == false)
    $workingDayCount++;
    } while ($workingDayCount < $workingDaysPeriod);
    echo "Fourteen WORKING days from now, it will be ".$testDate->format();
    ?>
    [/code]


    If you do take this code as I have given it and fix/debug it and get it working, and add code to enhance features, I would appreciate it if you post it to this thread.
    Copy linkTweet thisAlerts:
    @HelleshternauthorApr 20.2010 — Thank you [B]mavigozler[/B] for very wide description. I'm really appreciate your effort, however I'd like to rather extend my actual script than build another one.
    ×

    Success!

    Help @Helleshtern spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 BETA 5.16,
    whats_new: community page,
    up_next: more Davinci•003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinci•003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @AriseFacilitySolutions09,
    tipped: article
    amount: 1000 SATS,

    tipper: @Yussuf4331,
    tipped: article
    amount: 1000 SATS,

    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,
    )...