I'm trying to get days count between two dates from database. Date_from and Date_to. And I'm getting an error. Any help would be appreciated.
The code:
<?php
require('config/conn.php');
// Select all from table 'reguests'
$query = 'SELECT * FROM requests';
//Results from table
$result = mysqli_query($conn, $query);
//Fetch data
$requests = mysqli_fetch_all($result, MYSQLI_ASSOC);
//Free result from fetch
mysqli_free_result($result);
//Get Days Count Between Dates From And To
$dateFrom = $request['date_from'];
$dateTo = $requests['date_to'];
$daysDiff = floor(abs(strtotime($dateTo) - strtotime($dateFrom)) / (60*60*24));
//Close conn
mysqli_close($conn);
?>
Output:
<td><?php echo $daysDiff ?>
Your question title says to exclude weekends, but your code doesn't seem to try to?
To account for more complicated logic like that it's probably prudent to calculate a period and use it to iterate over days.
Something like this:
$dateFrom = new DateTime();
$dateTo = new DateTime( '+1 month +1 second' ); // Add 1s so period includes last day.
$period = new DatePeriod( $dateFrom, new DateInterval( 'P1D' ), $dateTo );
$days = 0;
foreach ( $period as $date ) {
$day = $date->format( 'l' );
if ( 'Saturday' !== $day && 'Sunday' !== $day ) {
$days ++;
}
}
echo $days; // 23
Please review your title, it's ambiguous with your problem. But to check difference between dates, please check the Php manual on the link: http://php.net/manual/en/datetime.diff.php
If you really wanna check if a day is weekend, please check: Checking if date is weekend PHP
Related
two dates 13-10-2017 and 13-02-2018. I want to separate this period in months like 13-10-2017 to 31-10-2-17, 01-11-2017 to 30-11-2017, 01-12-2017 to 31-12-2017, 01-01-2018 to 31-01-2018 and 01-02-2018 to 13-02-2018. What I did I can get the month names in the date period but not in the format I want.
Here is my code:
$start_date = new DateTime('13-10-2017');
$end_date = new DateTime('13-02-2018');
$date_interval = new DateInterval('P1M');
$date_period = new DatePeriod($start_date, $date_interval, $end_date);
# calculating number of days in the interval
$interval = $start_date->diff( $end_date );
$days = $interval->days;
# getting names of the months in the interval
$month_count = 0;
$month_names = array();
foreach ($date_period as $date) {
$month_names[] = $date->format('F');
$month_count++;
}
$month_name_string = implode(',', $month_names);
echo $start_date->format('d-m-Y').' to '.$end_date->format('d-m-Y'). ' is ' .$days.' days and month names are: '.$month_name_string;
The output I get :
13-10-2017 to 13-02-2018 is 123 days and month names are: October,November,December,January
You can, while iterating, do the following checks:
If the current month is in $start_date, use its day for the start date
If the current month is in $end_date, use its day for the last day
Else, use the 1 and maximum day of each month (using the t format character)
Also, you need to set the time to 00:00:01 in the final day in order to have it considered in the DateInterval:
<?php
$start_date = new DateTime('13-10-2017');
$end_date = new DateTime('13-02-2018');
$end_date->setTime(0, 0, 1); // important, to consider the last day!
$date_interval = new DateInterval('P1M');
$date_period = new DatePeriod($start_date, $date_interval, $end_date);
# calculating number of days in the interval
$interval = $start_date->diff( $end_date );
$days = $interval->days;
# getting names of the months in the interval
$dates = [];
foreach ($date_period as $date) {
$dateArr = [];
if ($date->format("Y-m") === $start_date->format("Y-m")) {
$dateArr["start"] = $start_date->format("d-m-Y");
}
else {
$dateArr["start"] = $date->format("01-m-Y");
}
if ($date->format("Y-m") === $end_date->format("Y-m")) {
$dateArr["end"] = $end_date->format("d-m-Y");
}
else {
$dateArr["end"] = $date->format("t-m-Y"); // last day of the month
}
$dates[] = $dateArr;
}
foreach ($dates as $date) {
echo $date["start"]." to ".$date["end"].PHP_EOL;
}
Demo
You can employ DateTime::modify function. E.g.:
$month_intervals = [];
foreach ($date_period as $date) {
$start = $date == $start_date ? $start_date : $date->modify('first day of this month');
$month_intervals[] = join([
$start->format('d-m-Y'),
$date->modify('last day of this month')->format('d-m-Y')
], ' to ');
}
$month_intervals[] = join([
(clone $end_date)->modify('first day of this month')->format('d-m-Y'),
$end_date->format('d-m-Y')
], ' to ');
echo implode(',', $month_intervals);
I have this function witch return an array of date. I need to jump on every seven days from now until last year.
$date[] = $lastDate = (new \DateTIme('NOW'))->format('Y-m-d');
for ($i = 1; $i < 54; ++$i) { // 54 -> number of weeks in a year
$date[] = $lastDate = date('Y-m-d', strtotime('-7 day', strtotime($lastDate)));
}
return array_reverse($date);
It works but I can do better.
I would like to change it because using 54 for the number of weeks in a year is not very good. (it can change)
So I want to use the DateInterval php class.
I can have the date of the last year with :
$lastYear = date('Y-m-d', strtotime('-1 year', strtotime($lastDate)));
But I don't know how I can have my array with all my dates with the DateInterval class.
Can someone help me? I'm very bad with date manipulation :( ...
Here is an example array about what I need:
["2015-07-06", "2015-07-13", "2015-07-20", "2015-07-27", "2015-08-03", "2015-08-10", "2015-08-17", "2015-08-24", "2015-08-31", "2015-09-07", "2015-09-14", "2015-09-21", "2015-09-28", "2015-10-05", "2015-10-12", "2015-10-19", "2015-10-26", "2015-11-02", "2015-11-09", "2015-11-16", "2015-11-23", "2015-11-30", "2015-12-07", "2015-12-14", "2015-12-21", "2015-12-28", "2016-01-04", "2016-01-11", "2016-01-18", "2016-01-25", "2016-02-01", "2016-02-08", "2016-02-15", "2016-02-22", "2016-02-29", "2016-03-07", "2016-03-14", "2016-03-21", "2016-03-28", "2016-04-04", "2016-04-11", "2016-04-18", "2016-04-25", "2016-05-02", "2016-05-09", "2016-05-16", "2016-05-23", "2016-05-30", "2016-06-06", "2016-06-13", "2016-06-20", "2016-06-27", "2016-07-04"]
PHP got it 's own native DateInterval object. Here 's a short example how to use it.
$oPeriodStart = new DateTime();
$oPeriodEnd = new DateTime('+12 months');
$oPeriod = new DatePeriod(
$oPeriodStart,
DateInterval::createFromDateString('7 days'),
$oPeriodEnd
);
foreach ($oPeriod as $oInterval) {
var_dump($oInterval->format('Y-m-d));
}
So what we 've done here? For a period of dates you need a start date, an end date and the interval. Just test it for yourself. Have fun.
Try this:
$timestamp = strtotime("last Sunday");
$sundays = array();
$last_year_timestamp = strtotime("-1 year ",$timestamp);
while($timestamp >= $last_year_timestamp) {
if (date("w", $timestamp) == 0) {
$sundays[] = date("Y-m-d", $timestamp);
$timestamp -= 86400*7;
continue;
}
$timestamp -= 86400;
}
I have a PHP script which records things based on the day. So it will have a weekly set of inputs you would enter.
I get the data correctly, but when i do $day ++; it will increment the day, going passed the end of the month without ticking the month.
example:
//12/29
//12/30
//12/31
//12/32
//12/33
Where it should look like
//12/29
//12/30
//12/31
//01/01
//01/02
My script is as follows:
$week = date ("Y-m-d", strtotime("last sunday"));
$day = $week;
$run = array(7); //this is actually defined in the data posted to the script, which is pretty much just getting the value of the array index for the query string.
foreach( $run as $key=>$value)
{
$num = $key + 1;
$items[] = "($num, $user, $value, 'run', '$day')";
echo "".$day;
$day ++;
}
Should I be manipulating the datetime differently for day incrementations?
You can use
$day = date("Y-m-d", strtotime($day . " +1 day"));
instead of
$day++;
See live demo in ideone
You refer to $day as a "datetime" but it is just a string - that is what date() returns. So when you do $day++ you are adding 1 to "2015-12-02". PHP will do everything it can to make "2015-12-02" into a number and then add 1 to it, which is not date math. Here is a simple example:
<?php
$name = "Fallenreaper1";
$name++;
echo $name
?>
This will output:
Fallenreaper2
This is how I would do it, using an appropriate data type (DateTime):
<?php
$day = new DateTime('last sunday');
$run = array(7);
foreach ($run as $key => $value) {
$num = $key + 1;
$dayStr = $day->format('Y-m-d');
$items[] = "($num, $user, $value, 'run', '$dayStr')";
echo $dayStr;
$day->modify('+1 day');
}
To increase time you should use strtotime("+1 day");
here is simple example of using it
<?php
$now_time = time();
for($i=1;$i<8;$i++) {
$now_time = strtotime("+1 day", $now_time);
echo date("Y-m-d", $now_time) . "<br>";
}
?>
I'm working with dates in php and I'm a little stumped
This is my code:
$day = 'Thursday';
$i = 0;
$o_date = new DateTime("2012-09-12 20:56:43 +18 hours");
$date = date_format($o_date, 'l');
$full = date_format($o_date, 'd-m-Y');
if($day!=$date) {
$date = new DateTime($date . " +1 days");
$i++;
}
$order_day = new DateTime($full . " +".$i." days");$order_day = date_format($order_day, 'D, d M');
return $order_day;
This is what I want it to do:
1) I've got a day in string format (eg. Thursday)
2) I've got an order date (eg. 2012-09-12 20:56:43)
I want to get that date and turn the day into a string (eg date_format($o_date, 'l'); so that will return Wednesday, I then want to count how many days until the next Thursday after the order date, which I've built an if loop for. I then want to get the original date and add the amount of days the $i has accumulated, then return the date in day format (eg. Thursday, 13 September, but for some reason my code isn't working. Can someone see what I've done wrong here?
Instead of a loop, why don't you use the numeric day and calculate:
$day = 'Thursday';
$day_names = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
$day_num = array_search($day, $day_names);
$o_date = new DateTime("2012-09-12 20:56:43 +18 hours");
$o_day_num = $o_date->format('w');
$day_diff = ($day_num - $o_day_num) % 7;
if ($day_diff == 0) { $day_diff = 7; }
$order_day = clone $o_date;
$order_day->add(new DateInterval("P".$day_diff."D"));
So I actually like #Barmar's idea better, but this is what I came up with... there were a number of issues in your original code, including formatting of the initial date, and the fact that you are creating a new object each time instead of working with the same one.
If you choose to use a loop, and I'm not sure you should... try this:
<?php
$day = 'Thursday';
$i = 0;
// Order Date
$o_date = new DateTime("2012-09-12 20:56:43 +18");
$date = $o_date->format('l');
while($day!==$date) {
$date = $o_date->add(new DateInterval('P1D'))->format('l');
$i++;
}
$order_day = $o_date->format('D, d M');
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()))