I am building a report for a client using php and codeigniter.
This report is a financial report, as such, I must reflect money collected since the beginning of the fiscal year. In this case, July 31st.
I already query the user for the date of the report, but how would I get php to know which fiscal year to take?
I have a rough idea, something along the lines of
'If Month-Day is before July 31, use current year-1
Else use current year'
But I do not know how I would code that, or if it would work, or if there is a more elegant way of doing the same thing.
I think your best bet is the dateTime class.
http://us3.php.net/manual/en/class.datetime.php
I think something like this is what you will need
public function getCurrentYear(DateTime $dateToCheck)
{
$today = new DateTime();
$currentYear = (int)$today->format('Y');
$endFiscalYear = new DateTime('31 July'); //year left out, so will default to this year
if($dateToCheck < $endFiscalYear){ //you need PHP >= 5.2.2 for this to work
$currentYear--;
}
return $currentYear;
}
You can set $today by doing something like :-
$today = new DateTime('20 June 2011');
Read more in the link above
Here is a slightly different version which should be a bit more robust as it will return the fiscal year of any date you give it, not just dates in the current year.
function getFiscalYear(DateTime $dateToCheck)
{
$fiscalYearEnd = '31 July';
$year = (int)$dateToCheck->format('Y');
$fiscalyearEndDate = new DateTime($fiscalYearEnd . ' ' . $year);
if($dateToCheck <= $fiscalyearEndDate){
$year--;
}
return $year;
}
use it like this :-
$dateToCheck = new DateTime('1 jan 2009'); // for example
$fiscalYear = getFiscalYear($dateToCheck);
This will return 2008
This version should work if your PHP version is < 5.2
function getFiscalYear($timestamp)
{
$year = (int)date('Y', $timestamp);
$fiscalYearEndDate = strtotime('31 July ' . $year);
if($timestamp < $fiscalYearEndDate) $year--;
return $year;
}
Use like this:-
$date = strtotime('1 Jan 2009');
fiscalYear = getFiscalYear($date);
Will return 2008
function get_fiscal_year($format = 'Y-m-d', $cutoff_date = '31 July') {
$fiscal_year = strtotime($cutoff_date);
if(time() < $fiscal_year)
$fiscal_year = strtotime($cutoff_date .' last year');
return date($format, $fiscal_year);
}
$fisical_year = get_fiscal_year();
$now = date('Y-m-d');
You then could use the function to query database with statement condition
transcation_date between $fisical_year and $now
If user gives the date: #givenDate and you want to search in your dateField (which is of type date), you can use something like:
WHERE dateField BETWEEN
DATE( CONCAT( YEAR(#givenDate)-(MONTH(#givenDate)<8), '-08-01' ))
AND DATE( CONCAT( 1+YEAR(#givenDate)-(MONTH(#givenDate)<8), '-07-31' ))
Related
I want to find entries in a month range based on date of a month
like if a user registered on 20th of a month, the script should get entries in a range from last 20th to next 20th of the month.
I.e if the script is running on any day before 20th of April the range should be March 20 - April 20, and if its running on 20th April or after then the range should be April 20 - May 20.
I looked up relative formats but it only lists functions for day names and weeks etc.
Is there any way the relative date format works like last n to next n. where n= 1 to 31.
Can anyone help? Thanks
Based on comment from Cully, here is an implementation (it still feels too messy, maybe there is an easier way to do it). It may explain the question a bit more.
function getFromDate($myDate, $nDate)
{
// sub 1 day till date is $nDate
while(true)
{
if($myDate->format('d')==$nDate)
break;
$myDate->sub(new DateInterval('P1D'));
}
return $myDate;
}
function getToDate($myDate, $nDate)
{
// add 1 day till date is $nDate
while(true)
{
$myDate->add(new DateInterval('P1D'));
if($myDate->format('d')==$nDate)
break;
}
return $myDate;
}
$timestamp = 1602107066; // An example user registration date, 7 October 2021
$nDate = gmdate("d", $timestamp);
$fromDate = getFromDate(new DateTime('now'), $nDate);
$toDate = getToDate(new DateTime('now'), $nDate);
echo $fromDate->format('d M y')."\r\n"; // 7 May 2021 (run on May 22 2021)
echo $toDate->format('d M y'); // 7 June 2021 (run on May 22 2021)
Do you mean something like this? It might not be exactly what you want, but can you use it to create what you want?
<?php
$numberOfDaysIWant = 20;
// March 20th, 2021, but you can use any date you want
$startDate = new DateTimeImmutable('2021-03-20');
$myPastDates = [];
$myFutureDates = [];
$currentDate = $startDate;
for($i = 0; $i < $numberOfDaysIWant; $i++) {
$currentDate = $currentDate->sub('P1D');
$myPastDates []= $currentDate;
}
$currentDate = $startDate;
for($i = 0; $i < $numberOfDaysIWant; $i++) {
$currentDate = $currentDate->add('P1D');
$myFutureDates []= $currentDate;
}
var_dump($myPastDates, $myFutureDates);
It's unclear from your question, but it sounds like maybe you want to get the $numberOfDaysIWant value based on the date of the selected month. If so, you could use this to get it:
<?php
$startDate = new DateTimeImmutable('2021-03-20');
$numberOfDaysIWant = (int) $startDate->format('j'); // "j" gives you the day of the month, without leading zeroes
I need a function that returns the year when a given date (day + month) occurs the first time from now on.
function year($day, $month) {
// ...
return $year;
}
$day and $year are two-digit numbers
E.g. the given date is '12/25' it should return '2016' (or '16'), but if the date is '02/25' it should return '2017' (or '17').
[Today is August 30, 2016]
Leap years may be disregarded and input doesn't have to be validated.
EDIT:
My attempt
year($day, $month) {
$today_day = date('d');
$today_month = date('m');
$year = date('y');
if($month > $today_month) {
return $year;
} else if ($month < $today_month) {
return $year + 1;
} else {
if($day >= $today_day) {
return $year;
} else {
return $year + 1;
}
}
}
Just compare the date you are checking against today. If it is today or earlier increment the year of the date. Otherwise do not. Then return that year.
DateTime() functionality makes this easy to do.
function year($day, $month) {
$date = new DateTime("{$month}/{$day}"); // defaults to current year
$today = new DateTime();
if ($date <= $today) {
$today->modify('+1 year');
}
return $today->format('Y');
}
echo year(6, 6); // 2017
echo year(12, 12); // 2016
Demo
I appreciate your effort! It was pretty good, but can certainly use some fine tuning. We could reduce the no. of unnecessary if statements.
The function accepts two parameters: month and date. Please be sure we follow the order while calling the function.
In the function, $date is the input date concatenated with the current year.
E.g: year(12,25) refers to the year where month is December (12) and day is 25.
year(12,25) would make $date as 2015-12-25.
function year($month, $day)
{
$date= date('Y').'-'.$month.'-'.$day;
if (strtotime($date) > time()) {
return date('y');
}
return (date('y')+1);
}
echo year(12,25); // 16
echo year(2,25); // 17
Now, all we need to do is check the timestamp of $date with the current timestamp- time().
strtotime($date) > time() input date timestamp is more than current timestamp. Which implies this date is yet to come in this year. So, we return the current year date('Y').
If the above if is not executed, it's obvious that this date has passed. Hence we return the next year date('Y') + 1.
I need a method for adding some number of months to any date in PHP. I know how to do this in MySQL but not in PHP. Here's my attempt:
MySQL:
SELECT DATE_ADD( '2011-12-29', INTERVAL 2
MONTH ) // Output "2012-02-29"
SELECT DATE_ADD( '2011-12-30', INTERVAL 2
MONTH ) // output "2012-02-29"
SELECT DATE_ADD( '2011-12-31', INTERVAL 2
MONTH ) // output "2012-02-29"
PHP:
$date = date_create('2011-12-29');
$date->modify("+1 month");
echo $date->format("Y-m-d");
// Output is "2012-01-29" -- this is correct
$date = date_create('2011-12-30');
$date->modify("+2 month");
echo $date->format("Y-m-d");
// Output is "2012-03-01" -- I need the answer like "2012-02-29"
$date = date_create('2011-12-31');
$date->modify("+2 month");
echo $date->format("Y-m-d");
// Output is "2012-03-02" -- I need the answer like "2012-02-29"
The MySQL output is correct. I need the same output in PHP.
If you use PHP5 >= 5.3, all you need to do is use
$date->modify("last day of +2 months");
as suggested in other answers. But if you use 5.2 you could try altering your code like this:
Class DateTimeM Extends DateTime
{
public function modify ($modify)
{
$day = $this->format ('d');
$buf = new DateTime ($this->format ('Y-m-01\TH:i:sO'));
$buf->modify ($modify);
if ($day > $buf->format ('t'))
{
$this->setDate ($buf->format ('Y'), $buf->format ('m'), $buf->format ('t'));
}
else
{
$this->setDate ($buf->format ('Y'), $buf->format ('m'), $day);
}
$this->setTime ($buf->format ('H'), $buf->format ('i'), $buf->format ('s'));
return $this;
}
}
$date = new DateTimeM ('2011-12-29');
$date->modify("+2 month");
echo $date->format("Y-m-d");
I suggest adding the class definition to a separate file and require_once() it. Switch from date_create() to using the new class's object constructor. The new class's modify() method will modify the date using the first day of the original given month instead of the last and check if the original given day of month is larger than the new month's number of days.
A benefit of this approach is that it will work for say $date->modify ('2 year 2 month') as well.
Here's a solution that might do the job for you:
function addMonths(DateTime $date, $months) {
$last = clone $date;
$last = $last->modify("last day of +$months months")->getTimestamp();
$default = clone $date;
$default = $default->modify("+$months months")->getTimestamp();
return $date->setTimestamp(min($last, $default));
}
$date = new DateTime('2011-12-31');
$laterDate = addMonths($date, 2);
This will work regardless of which day of the month you start with.
Hope it surely helps you.
I just try with adding days instead of adding months
$MonthAdded = strtotime("+60 days",strtotime('2011-12-31'));
echo "After adding month: ".date('Y-m-d', $MonthAdded)."<br>";
Output:
After adding month: 2012-02-29
Read the link Dagon posted in the comments to your question. Extrapolating on the answer there, I tried this and it works:
$d = new DateTime("2011-12-31");
$d->modify("last day of +2 months");
echo $d->format("Y-m-d");
// result is 2012-02-29
$d = new DateTime("2012-12-31");
$d->modify("last day of +2 months");
echo $d->format("Y-m-d");
// result is 2013-02-28
I know about the unwanted behaviour of PHP's function
strtotime
For example, when adding a month (+1 month) to dates like: 31.01.2011 -> 03.03.2011
I know it's not officially a PHP bug, and that this solution has some arguments behind it, but at least for me, this behavior has caused a lot waste of time (in the past and present) and I personally hate it.
What I found even stranger is that for example in:
MySQL: DATE_ADD('2011-01-31', INTERVAL 1 MONTH) returns 2011-02-28
or
C# where new DateTime(2011, 01, 31).AddMonths(1); will return 28.02.2011
wolframalpha.com giving 31.01.2013 + 1 month as input; will return Thursday, February 28, 2013
It sees to me that others have found a more decent solution to the stupid question that I saw alot in PHP bug reports "what day will it be, if I say we meet in a month from now" or something like that. The answer is: if 31 does not exists in next month, get me the last day of that month, but please stick to next month.
So MY QUESTION IS: is there a PHP function (written by somebody) that resolves this not officially recognized bug? As I don't think I am the only one who wants another behavior when adding / subtracting months.
I am particulary interested in solutions what also work not just for the end of the month, but a complete replacement of strtotime. Also the case strotime +n months should be also dealt with.
Happy coding!
what you need is to tell PHP to be smarter
$the_date = strtotime('31.01.2011');
echo date('r', strtotime('last day of next month', $the_date));
$the_date = strtotime('31.03.2011');
echo date('r', strtotime('last day of next month', $the_date));
assuming you are only interesting on the last day of next month
reference - http://www.php.net/manual/en/datetime.formats.relative.php
PHP devs surely don't consider this as bug. But in strtotime's docs there are few comments with solutions for your problem (look for 28th Feb examples ;)), i.e. this one extending DateTime class:
<?php
// this will give us 2010-02-28 ()
echo PHPDateTime::DateNextMonth(strftime('%F', strtotime("2010-01-31 00:00:00")), 31);
?>
Class PHPDateTime:
<?php
/**
* IA FrameWork
* #package: Classes & Object Oriented Programming
* #subpackage: Date & Time Manipulation
* #author: ItsAsh <ash at itsash dot co dot uk>
*/
final class PHPDateTime extends DateTime {
// Public Methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Calculate time difference between two dates
* ...
*/
public static function TimeDifference($date1, $date2)
$date1 = is_int($date1) ? $date1 : strtotime($date1);
$date2 = is_int($date2) ? $date2 : strtotime($date2);
if (($date1 !== false) && ($date2 !== false)) {
if ($date2 >= $date1) {
$diff = ($date2 - $date1);
if ($days = intval((floor($diff / 86400))))
$diff %= 86400;
if ($hours = intval((floor($diff / 3600))))
$diff %= 3600;
if ($minutes = intval((floor($diff / 60))))
$diff %= 60;
return array($days, $hours, $minutes, intval($diff));
}
}
return false;
}
/**
* Formatted time difference between two dates
*
* ...
*/
public static function StringTimeDifference($date1, $date2) {
$i = array();
list($d, $h, $m, $s) = (array) self::TimeDifference($date1, $date2);
if ($d > 0)
$i[] = sprintf('%d Days', $d);
if ($h > 0)
$i[] = sprintf('%d Hours', $h);
if (($d == 0) && ($m > 0))
$i[] = sprintf('%d Minutes', $m);
if (($h == 0) && ($s > 0))
$i[] = sprintf('%d Seconds', $s);
return count($i) ? implode(' ', $i) : 'Just Now';
}
/**
* Calculate the date next month
*
* ...
*/
public static function DateNextMonth($now, $date = 0) {
$mdate = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
list($y, $m, $d) = explode('-', (is_int($now) ? strftime('%F', $now) : $now));
if ($date)
$d = $date;
if (++$m == 2)
$d = (($y % 4) === 0) ? (($d <= 29) ? $d : 29) : (($d <= 28) ? $d : 28);
else
$d = ($d <= $mdate[$m]) ? $d : $mdate[$m];
return strftime('%F', mktime(0, 0, 0, $m, $d, $y));
}
}
?>
Here's the algorithm you can use. It should be simple enough to implement yourself.
Have the original date and the +1 month date in variables
Extract the month part of both variables
If the difference is greater than 1 month (or if the original is December and the other is not January) change the latter variable to the last day of the next month. You can use for example t in date() to get the last day: date( 't.m.Y' )
Had the same issue recently and ended up writing a class that handles adding/subtracting various time intervals to DateTime objects.
Here's the code:
https://gist.github.com/pavlepredic/6220041#file-gistfile1-php
I've been using this class for a while and it seems to work fine, but I'm really interested in some peer review. What you do is create a TimeInterval object (in your case, you would specify 1 month as the interval) and then call addToDate() method, making sure you set $preventMonthOverflow argument to true. The code will make sure that the resulting date does not overflow into next month.
Sample usage:
$int = new TimeInterval(1, TimeInterval::MONTH);
$date = date_create('2013-01-31');
$future = $int->addToDate($date, true);
echo $future->format('Y-m-d');
Resulting date is:
2013-02-28
Here is an implementation of an improved version of Juhana's answer above:
<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
$addMon = clone $currentDate;
$addMon->add(new DateInterval("P1M"));
$nextMon = clone $currentDate;
$nextMon->modify("last day of next month");
if ($addMon->format("n") == $nextMon->format("n")) {
$recurDay = $createdDate->format("j");
$daysInMon = $addMon->format("t");
$currentDay = $currentDate->format("j");
if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
$addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
}
return $addMon;
} else {
return $nextMon;
}
}
This version takes $createdDate under the presumption that you are dealing with a recurring monthly period, such as a subscription, that started on a specific date, such as the 31st. It always takes $createdDate so late "recurs on" dates won't shift to lower values as they are pushed forward thru lesser-valued months (e.g., so all 29th, 30th or 31st recur dates won't eventually get stuck on the 28th after passing thru a non-leap-year February).
Here is some driver code to test the algorithm:
$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;
$next = sameDateNextMonth($createdDate, $createdDate);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
foreach(range(1, 12) as $i) {
$next = sameDateNextMonth($createdDate, $next);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
}
Which outputs:
created date = 2015-03-31
next date = 2015-04-30
next date = 2015-05-31
next date = 2015-06-30
next date = 2015-07-31
next date = 2015-08-31
next date = 2015-09-30
next date = 2015-10-31
next date = 2015-11-30
next date = 2015-12-31
next date = 2016-01-31
next date = 2016-02-29
next date = 2016-03-31
next date = 2016-04-30
I have solved it by this way:
$startDate = date("Y-m-d");
$month = date("m",strtotime($startDate));
$nextmonth = date("m",strtotime("$startDate +1 month"));
if((($nextmonth-$month) > 1) || ($month == 12 && $nextmonth != 1))
{
$nextDate = date( 't.m.Y',strtotime("$initialDate +1 week"));
}else
{
$nextDate = date("Y-m-d",strtotime("$initialDate +1 month"));
}
echo $nextDate;
Somewhat similar to the Juhana's answer but more intuitive and less complications expected. Idea is like this:
Store original date and the +n month(s) date in variables
Extract the day part of both variables
If days do not match, subtract number of days from the future date
Plus side of this solution is that works for any date (not just the border dates) and it also works for subtracting months (by putting - instead of +).
Here is an example implementation:
$start = mktime(0,0,0,1,31,2015);
for ($contract = 0; $contract < 12; $contract++) {
$end = strtotime('+ ' . $contract . ' months', $start);
if (date('d', $start) != date('d', $end)) {
$end = strtotime('- ' . date('d', $end) . ' days', $end);
}
echo date('d-m-Y', $end) . '|';
}
And the output is following:
31-01-2015|28-02-2015|31-03-2015|30-04-2015|31-05-2015|30-06-2015|31-07-2015|31-08-2015|30-09-2015|31-10-2015|30-11-2015|31-12-2015|
function ldom($m,$y){
//return tha last date of a given month based on the month and the year
//(factors in leap years)
$first_day= strtotime (date($m.'/1/'.$y));
$next_month = date('m',strtotime ( '+32 day' , $first_day)) ;
$last_day= strtotime ( '-1 day' , strtotime (date($next_month.'/1/'.$y)) ) ;
return $last_day;
}
Does anyone have a PHP snippet to calculate the next business day for a given date?
How does, for example, YYYY-MM-DD need to be converted to find out the next business day?
Example:
For 03.04.2011 (DD-MM-YYYY) the next business day is 04.04.2011.
For 08.04.2011 the next business day is 11.04.2011.
This is the variable containing the date I need to know the next business day for
$cubeTime['time'];
Variable contains: 2011-04-01
result of the snippet should be: 2011-04-04
Next Weekday
This finds the next weekday from a specific date (not including Saturday or Sunday):
echo date('Y-m-d', strtotime('2011-04-05 +1 Weekday'));
You could also do it with a date variable of course:
$myDate = '2011-04-05';
echo date('Y-m-d', strtotime($myDate . ' +1 Weekday'));
UPDATE: Or, if you have access to PHP's DateTime class (very likely):
$date = new DateTime('2018-01-27');
$date->modify('+7 weekday');
echo $date->format('Y-m-d');
Want to Skip Holidays?:
Although the original poster mentioned "I don't need to consider holidays", if you DO happen to want to ignore holidays, just remember - "Holidays" is just an array of whatever dates you don't want to include and differs by country, region, company, person...etc.
Simply put the above code into a function that excludes/loops past the dates you don't want included. Something like this:
$tmpDate = '2015-06-22';
$holidays = ['2015-07-04', '2015-10-31', '2015-12-25'];
$i = 1;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
while (in_array($nextBusinessDay, $holidays)) {
$i++;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
}
I'm sure the above code can be simplified or shortened if you want. I tried to write it in an easy-to-understand way.
For UK holidays you can use
https://www.gov.uk/bank-holidays#england-and-wales
The ICS format data is easy to parse. My suggestion is...
# $date must be in YYYY-MM-DD format
# You can pass in either an array of holidays in YYYYMMDD format
# OR a URL for a .ics file containing holidays
# this defaults to the UK government holiday data for England and Wales
function addBusinessDays($date,$numDays=1,$holidays='') {
if ($holidays==='') $holidays = 'https://www.gov.uk/bank-holidays/england-and-wales.ics';
if (!is_array($holidays)) {
$ch = curl_init($holidays);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$ics = curl_exec($ch);
curl_close($ch);
$ics = explode("\n",$ics);
$ics = preg_grep('/^DTSTART;/',$ics);
$holidays = preg_replace('/^DTSTART;VALUE=DATE:(\\d{4})(\\d{2})(\\d{2}).*/s','$1-$2-$3',$ics);
}
$addDay = 0;
while ($numDays--) {
while (true) {
$addDay++;
$newDate = date('Y-m-d', strtotime("$date +$addDay Days"));
$newDayOfWeek = date('w', strtotime($newDate));
if ( $newDayOfWeek>0 && $newDayOfWeek<6 && !in_array($newDate,$holidays)) break;
}
}
return $newDate;
}
function next_business_day($date) {
$add_day = 0;
do {
$add_day++;
$new_date = date('Y-m-d', strtotime("$date +$add_day Days"));
$new_day_of_week = date('w', strtotime($new_date));
} while($new_day_of_week == 6 || $new_day_of_week == 0);
return $new_date;
}
This function should ignore weekends (6 = Saturday and 0 = Sunday).
This function will calculate the business day in the future or past. Arguments are number of days, forward (1) or backwards(0), and a date. If no date is supplied todays date will be used:
// returned $date Y/m/d
function work_days_from_date($days, $forward, $date=NULL)
{
if(!$date)
{
$date = date('Y-m-d'); // if no date given, use todays date
}
while ($days != 0)
{
$forward == 1 ? $day = strtotime($date.' +1 day') : $day = strtotime($date.' -1 day');
$date = date('Y-m-d',$day);
if( date('N', strtotime($date)) <= 5) // if it's a weekday
{
$days--;
}
}
return $date;
}
What you need to do is:
Convert the provided date into a timestamp.
Use this along with the or w or N formatters for PHP's date command to tell you what day of the week it is.
If it isn't a "business day", you can then increment the timestamp by a day (86400 seconds) and check again until you hit a business day.
N.B.: For this is really work, you'd also need to exclude any bank or public holidays, etc.
I stumbled apon this thread when I was working on a Danish website where I needed to code a "Next day delivery" PHP script.
Here is what I came up with (This will display the name of the next working day in Danish, and the next working + 1 if current time is more than a given limit)
$day["Mon"] = "Mandag";
$day["Tue"] = "Tirsdag";
$day["Wed"] = "Onsdag";
$day["Thu"] = "Torsdag";
$day["Fri"] = "Fredag";
$day["Sat"] = "Lørdag";
$day["Sun"] = "Søndag";
date_default_timezone_set('Europe/Copenhagen');
$date = date('l');
$checkTime = '1400';
$date2 = date(strtotime($date.' +1 Weekday'));
if( date( 'Hi' ) >= $checkTime) {
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Saturday'){
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Sunday') {
$date2 = date(strtotime($date.' +2 Weekday'));
}
echo '<p>Næste levering: <span>'.$day[date("D", $date2)].'</span></p>';
As you can see in the sample code $checkTime is where I set the time limit which determines if the next day delivery will be +1 working day or +2 working days.
'1400' = 14:00 hours
I know that the if statements can be made more compressed, but I show my code for people to easily understand the way it works.
I hope someone out there can use this little snippet.
Here is the best way to get business days (Mon-Fri) in PHP.
function days()
{
$week=array();
$weekday=["Monday","Tuesday","Wednesday","Thursday","Friday"];
foreach ($weekday as $key => $value)
{
$sort=$value." this week";
$day=date('D', strtotime($sort));
$date=date('d', strtotime($sort));
$year=date('Y-m-d', strtotime($sort));
$weeks['day']= $day;
$weeks['date']= $date;
$weeks['year']= $year;
$week[]=$weeks;
}
return $week;
}
Hope this will help you guys.
Thanks,.
See the example below:
$startDate = new DateTime( '2013-04-01' ); //intialize start date
$endDate = new DateTime( '2013-04-30' ); //initialize end date
$holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday
$interval = new DateInterval('P1D'); // set the interval as 1 day
$daterange = new DatePeriod($startDate, $interval ,$endDate);
foreach($daterange as $date){
if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday))
$result[] = $date->format("Y-m-d");
}
echo "<pre>";print_r($result);
For more info: http://goo.gl/YOsfPX
You could do something like this.
/**
* #param string $date
* #param DateTimeZone|null|null $DateTimeZone
* #return \NavigableDate\NavigableDateInterface
*/
function getNextBusinessDay(string $date, ? DateTimeZone $DateTimeZone = null):\NavigableDate\NavigableDateInterface
{
$Date = \NavigableDate\NavigableDateFacade::create($date, $DateTimeZone);
$NextDay = $Date->nextDay();
while(true)
{
$nextDayIndexInTheWeek = (int) $NextDay->format('N');
// check if the day is between Monday and Friday. In DateTime class php, Monday is 1 and Friday is 5
if ($nextDayIndexInTheWeek >= 1 && $nextDayIndexInTheWeek <= 5)
{
break;
}
$NextDay = $NextDay->nextDay();
}
return $NextDay;
}
$date = '2017-02-24';
$NextBussinessDay = getNextBusinessDay($date);
var_dump($NextBussinessDay->format('Y-m-d'));
Output:
string(10) "2017-02-27"
\NavigableDate\NavigableDateFacade::create($date, $DateTimeZone), is provided by php library available at https://packagist.org/packages/ishworkh/navigable-date. You need to first include this library in your project with composer or direct download.
I used below methods in PHP, strtotime() does not work specially in leap year February month.
public static function nextWorkingDay($date, $addDays = 1)
{
if (strlen(trim($date)) <= 10) {
$date = trim($date)." 09:00:00";
}
$date = new DateTime($date);
//Add days
$date->add(new DateInterval('P'.$addDays.'D'));
while ($date->format('N') >= 5)
{
$date->add(new DateInterval('P1D'));
}
return $date->format('Y-m-d H:i:s');
}
This solution for 5 working days (you can change if you required for 6 or 4 days working). if you want to exclude more days like holidays then just check another condition in while loop.
//
while ($date->format('N') >= 5 && !in_array($date->format('Y-m-d'), self::holidayArray()))