I'm trying to calculate National Sovereignty Day of Argentina which is celebrated on the Monday closest to 20 November.
I tried to find PHP solutions here but just found a Ruby solution: Get the closest date of a specific week day
How can I implement this for PHP?
Using $date->format("N") you will get a numeric representation of the weekday (1-7 for Monday-Sunday). If its greater than 4, which is greater than Thursday, select the next Monday. If not, it's the previous Monday.
If $date->format("N") === 1, it's the date provided, and we don't need any modifications.
$date = new DateTime("November 20th");
$dayOfWeek = $date->format("N");
if ($dayOfWeek > 1) {
$date->modify($dayOfWeek > 4 ? 'next monday' : 'previous monday');
}
echo $date->format("Y-m-d");
Live demo
Could try something like this:
<?php
function getSovDay($year)
{
$date = new \DateTime($year."-11-20");
$weekDay = $date->format("N");
if ($weekDay == 1)
{
return $date;
} elseif ($weekDay <= 4) {
return $date->modify("previous monday");
} else {
return $date->modify("next monday");
}
}
for($i = 2000; $i <= 2200; $i++)
{
echo getSovDay($i)->format("Y-m-d")."\n";
}
I am trying to show results of each month.
Im having this for loop:
foreach ($overview as $day) {
$year = date("Y") - 1;
if ($day->user == $info->id) {
$startDate = new DateTime($day->Calendar_startdate);
$endDate = new DateTime($day->Calendar_enddate);
$s = $startDate->format('Y-m-d');
$e = $endDate->format('Y-m-d');
if ($s > $year) {
$workdays = number_of_working_days($s, $e);
$daysleft = $daysleft + $workdays;
} else {
}
}
}
This for loop is also in an if statement which echos the months.
Now I need to let it work for the months January, February etc...
I am able to not show results if in the previous year which works well.
If you want to compare $s with $year just change $year to :
$time = new DateTime('now');
/*** you can use `now` for today
/* or you can change to a fixed date exmp: 2016-01-01
*/
$year = $time->modify('-1 year')->format('Y-m-d');
Than you can compare $s > $year
I fixed by checking each month if it contained for example -01-
DB::table('Calendar')->where('Calendar_startdate', 'like','%' . $monthnumber . '%')->where('user', $info->id)->where('Calendar_type',2)->get();
I have to show how many users signed up each month after certain month and certain year upto current month and current year.
For example: if we take data from 3rd month of 2015.
So the output will be like:
03/2015
04/2015
05/2015
...
and so on upto
12/2015
01/2016
as currently 1st month of 2016 is running.
Any help??
Here is some code I have tried:
$c_month = date('m');
$c_year = date('Y');
$year_array = array("2015","2016","2017","2018","2019","2020","2021");
foreach($year_array as $y_a){
for($i=1;$i<=12;$i++){
if(($i == 1 || $i == 2) && $y_a == '2015'){
continue;
}
if($i > $c_month && $y_a == $c_year){
break 2;
}
$chnge_i = strlen($i);
if ($chnge_i == 1) {
$put_o = '0' . $i;
}
else{
$put_o = $i;
}
echo $put_o.'/'.$y_a.'<br>';
}
}
It is giving correct values except if current month number is 12 and also i don't think this is the best way to do it.
you can use strtotime and date to do this.
$start=strtotime('2015-03-01');
while ($start <= time()){
echo date('m/Y',$start) . "\n";
$start=strtotime('+1 month', $start);
}
Output:
03/2015
04/2015
05/2015
06/2015
07/2015
08/2015
09/2015
10/2015
11/2015
12/2015
01/2016
Note: this is only one of the ways.
Important Note: remember to set timezone (i would prefer UTC) date_default_timezone_set
you should do the difference like below
//previous date
$start = (new DateTime('2013-12-02'))->modify('first day of this month');
// current date
$end = (new DateTime('2015-12-06'))->modify('first day of this month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("m/Y") . "<br>\n";
}
Hope this helps.
I want to only shows result for the current month, but I have no idea how to do this, my current output is like this.
Output
2014-04-11
-> array
2014-04-11
2014-04-05
2014-03-29
PHP
$date = date('Y-m-d');
echo $date;
echo "<pre>";
foreach ($submissions as $test){
if($date >= substr($test['thing']['created'], 0, 10)){
echo substr($test['thing']['created'], 0, 10);
echo "<br>";
}
}
echo "</pre>";
My current code wont work as its only checking if the whole number is greater or equal to, any ideas anyone?
Just try with strtotime:
$year = date('Y');
$month = date('m');
foreach ($submissions as $test) {
$timestamp = strtotime($test['thing']['created']);
$testYear = date('Y', $timestamp);
$testMonth = date('m', $timestamp);
if (($month >= $testMonth && $year == $testYear) || $year > $testYear) {
// test passed
}
}
If your problem is to have only results of current month :
$date = date('Y-m');
echo "<pre>";
foreach ($submissions as $test){
// if month & year is equal
if($date == substr($test['thing']['created'], 0, 7)){
echo substr($test['thing']['created'], 0, 10);
echo "<br>";
}
}
echo "</pre>";
If you want to sort it, you will have to convert to timestamp
i'm not a pro in php but take a look here : http://fr2.php.net/manual/fr/function.date.php
does date('m') would be a solution for your problem?
You can try 2 ways :
convert them to timestamp, then compare the int
If you are taking the dates frome a DB, ORDER BY date in the query
Variable for current month first $cur_m=date('m')
Explode your variable in loop with -.
$p = explode('-',$test['thing']['created']);
in loop check for current month like below
if($p[1]==$cur_m){ your code... }
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()))