patternphpModerate
Calculate future date based on business days
Viewed 0 times
businessdatefuturecalculatebaseddays
Problem
I've written a program for calculating the future date after certain number of business days.
But the problem with this function is that it doesn't check the last date of business day for
I've made a solution to this problem as
But it doesn't seems good.
Usage Example
I'm using this method for calculating the shipment date on which a product will be delivered to the customer.
The
function add_business_days($startdate,$businessdays,$holidays,$dateformat){
$i=1;
$dayx = strtotime($startdate);
while($i < $businessdays){
$day = date('N',$dayx);
$date = date('Y-m-d',$dayx);
if($day < 6 && !in_array($date,$holidays))$i++;
$dayx = strtotime($date.' +1 day');
}
return date($dateformat,$dayx);
}But the problem with this function is that it doesn't check the last date of business day for
Saturday and Sunday. Also, the last day could be the holiday. Can anyone provide me a better solution for this?I've made a solution to this problem as
function add_business_days($startdate,$businessdays,$holidays,$dateformat){
$i=1;
$dayx = strtotime($startdate);
while($i <= $businessdays){
$day = date('N',$dayx);
$date = date('Y-m-d',$dayx);
if($day < 6 && !in_array($date,$holidays))$i++;
$dayx = strtotime($date.' +1 day');
}
return date($dateformat,strtotime(date('Y-m-d', $dayx) . ' -1 day'));
}But it doesn't seems good.
Usage Example
I'm using this method for calculating the shipment date on which a product will be delivered to the customer.
$startdate = "2014-05-28"; //Order placing date
$businessdays = 7; //number of days for delivery
$holidays = array('2014-05-30','2014-06-03'); //array of dates having holidays. excluding business days.
$dateformat = 'd-m-Y'; //output date format for displaying.
$delivery = add_business_days($startdate, $businessdays, $holidays, $dateformat);The
$delivery is supposed to have date 09-06-2014 but the first code returns 07-06-2014 which doesn't check for the last date in loop for weekends (Saturday or Sunday). I've made the solution in the second program by execution the loop one more time and then return the previous date. But this approach doesn't seem good. Any suggestions on notSolution
I propose a class,
In the above example the nonBusinessDays of the week are SATURDAY and FRIDAY, and 1st and 2nd of June are holidays. In that case, 3 business days from now is June 5th.
This can probably be improved further, let your imagination run wild :P
BusinessDayCalculator, which would handle all this logic in one place. Here's an example:date = $startDate;
$this->holidays = $holidays;
$this->nonBusinessDays = $nonBusinessDays;
}
public function addBusinessDays($howManyDays) {
$i = 0;
while ($i date->modify("+1 day");
if ($this->isBusinessDay($this->date)) {
$i++;
}
}
}
public function getDate() {
return $this->date;
}
private function isBusinessDay(DateTime $date) {
if (in_array((int)$date->format('N'), $this->nonBusinessDays)) {
return false; //Date is a nonBusinessDay.
}
foreach ($this->holidays as $day) {
if ($date->format('Y-m-d') == $day->format('Y-m-d')) {
return false; //Date is a holiday.
}
}
return true; //Date is a business day.
}
}
$calculator = new BusinessDaysCalculator(
new DateTime(), // Today
[new DateTime("2014-06-01"), new DateTime("2014-06-02")],
[BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::FRIDAY]
);
$calculator->addBusinessDays(3); // Add three business days
var_dump($calculator->getDate());In the above example the nonBusinessDays of the week are SATURDAY and FRIDAY, and 1st and 2nd of June are holidays. In that case, 3 business days from now is June 5th.
This can probably be improved further, let your imagination run wild :P
Code Snippets
<?php
class BusinessDaysCalculator {
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
const SUNDAY = 7;
/**
* @param DateTime $startDate Date to start calculations from
* @param DateTime[] $holidays Array of holidays, holidays are no conisdered business days.
* @param int[] $nonBusinessDays Array of days of the week which are not business days.
*/
public function __construct(DateTime $startDate, array $holidays, array $nonBusinessDays) {
$this->date = $startDate;
$this->holidays = $holidays;
$this->nonBusinessDays = $nonBusinessDays;
}
public function addBusinessDays($howManyDays) {
$i = 0;
while ($i < $howManyDays) {
$this->date->modify("+1 day");
if ($this->isBusinessDay($this->date)) {
$i++;
}
}
}
public function getDate() {
return $this->date;
}
private function isBusinessDay(DateTime $date) {
if (in_array((int)$date->format('N'), $this->nonBusinessDays)) {
return false; //Date is a nonBusinessDay.
}
foreach ($this->holidays as $day) {
if ($date->format('Y-m-d') == $day->format('Y-m-d')) {
return false; //Date is a holiday.
}
}
return true; //Date is a business day.
}
}
$calculator = new BusinessDaysCalculator(
new DateTime(), // Today
[new DateTime("2014-06-01"), new DateTime("2014-06-02")],
[BusinessDaysCalculator::SATURDAY, BusinessDaysCalculator::FRIDAY]
);
$calculator->addBusinessDays(3); // Add three business days
var_dump($calculator->getDate());Context
StackExchange Code Review Q#51895, answer score: 10
Revisions (0)
No revisions yet.