Ignoring holidays in week working days in PHP - php

I want to get all the working days of current week by ignoring weekends (Saturday and Sunday) also I want to ignore holidays as well (holiday list are in database)
Here is my code to get all the working days of current weeks (excluding Saturday and Sunday)
$holiday_date_list = []; // from database
$dt = new DateTime();
$dates = [];
for ($d = 1; $d <= 5; $d++)
{
$dt->setISODate($dt->format('o'), $dt->format('W'), $d);
$dates[$dt->format('D')] = $dt->format('Y-m-d');
}
foreach ($dates as $key => $value)
{
echo $value . "<br>";
}
How can exclude holiday list from the above script?

Related

How to save date and day into separate array without sundays?

I am trying to save a series of five dates into an array to be called. The date has no range since it is taking the current date to start with.
I would like to save without any Sundays as delivery is not an option for Sunday in my case. I am saving both dates and day in separate arrays.
$date = new DateTime("+ 1 day", new DateTimeZone('Asia/Thailand') );
for ($i=1; $i<=5; $i++) {
$date->modify("+1 weekday");
$delivery_dates[] = $date->format("m/d/Y");
$delivery_days[] = $date->format("l, d F Y");
}
At the moment, I am getting the following -
Sunday, Monday, Tuesday, Wednesday, Thursday (inclusive of the dates for each day in d F Y format)
Is there a way I can get the following -
Monday, Tuesday, Wednesday, Thursday, Friday (inclusive of the dates for each day in d F Y format)?
For every Sunday I would like to +1 day so it makes an available day for delivery, on Monday.
I have used the following -
for ($i=1; $i<=5; $i++) {
$date->modify("+1 weekday");
if ($date->format("N") !== 7 {
$delivery_dates[] = $date->format("m/d/Y");
$delivery_days[] = $date->format("l, d F Y");
}
}
The codes above still display Sunday.
$from = '2018-10-10';
$to = '2018-12-10';
$start = new \DateTime($from);
$end = new \DateTime($to);
$interval = \DateInterval::createFromDateString('1 day'); // 1 day === P1D, 5 month and 5 years === P5M5Y
$period = new \DatePeriod($start, $interval, $end); // A date period allows iteration over a set of dates and times, recurring at regular intervals, over a given period.
// new \DatePeriod(10-10-2010, 5, 30-10-2010) ===> [10-10-2010, 15-10-2010, 20-10-2010, 25-10-2010, 30-10-2010]
$result = [];
foreach ($period as $day) {
if (! in_array($day->format('w'), [0, 6])) { // check every date in period, ->format('w'): w - number of day; Monday = 1 or 7 (depends on wat day declared first)
$result['date'][] = $day->format("m/d/Y");
$result['day'][] = $day->format("l, d F Y");
}
}
Assuming you can use Carbon, one way to implement is to generate the range with the help of a while-loop, and only add a date if it is not a Sunday, while ensuring that you'll get the required amount of days, in your case, 5.
/**
* #param int $amount
* #return Carbon[]
*/
public function getDeliveryDates($amount = 5): array
{
$days = [];
$current = Carbon::today();
while (\count($days) < $amount) {
$day = clone $current; // addDay works on instance, cloning it
$day->addDay();
$current = $day; // setting current to current day, so that it will iterate
if ($current->isSunday()) {
continue;
}
$days[] = $current;
}
return $days;
}
Then you can just format your date. If you still want two arrays with the info, you just need to iterate over the generated array:
$formattedDates = [];
$formattedDays = [];
foreach (getDeliveryDates() as $date) {
$formattedDates[] = $date->format('m/d/Y');
$formattedDays[] = $date->format('l, d F Y');
}

Get Mondays of every second month

I am trying to get the date of every monday skipping a month each time but I keep getting only the monday of the first week. This is my code:
$begin = new \DateTime("2017-04-01");
$end = new \DateTime("2017-08-31");
$interval = \DateInterval::createFromDateString("next monday of +2 months");
$period = new \DatePeriod($begin, $interval, $end);
foreach ( $period as $dt )
{
// echo the date for each monday found in the second month
}
Any help would be greatly appreciated.
You seem to have mixed the $begin and $end values. Also, the DateInterval will only have one Monday every single month. I was not able to find a interval expression to get every Monday in every other month, so I did the filtering manually. In this example we use the month from the begin date, and includes the Mondays from that date, skip two months and so on.
<?php
$end = new \DateTime("2017-04-01");
$begin = new \DateTime("2007-08-31");
$month_even = ((int) $begin->format('m')) % 2 === 0;
$interval = \DateInterval::createFromDateString("next monday");
$period = new \DatePeriod($begin, $interval, $end);
foreach ($period as $dt) {
// Check if we want to show even months, make sure that the current month is even
// or, if we want to show odd months, the month should be odd.
if ((((int) $dt->format('m')) % 2 === 0) === $month_even) {
echo $dt->format('d-m-Y') . PHP_EOL;
}
}
Outputs:
31-08-2007
01-10-2007
[...]
06-02-2017
13-02-2017
20-02-2017
27-02-2017

PHP Get recurring dates for specific weekday

How to get all recurring dates for chosen week of the day?
For example, today is Wednesday 15/02/2017 and if I choose Thursday how to get next 5 dates starting next Thursday like:
$dates = array(
[0] => "16/02/2017",
[1] => "23/02/2017",
[2] => "02/03/2017",
[3] => "09/03/2017",
[4] => "16/03/2017");
If I choose Tuesday, get dates starting 21/02/2017, which is next Tuesday
You can use strtotime to generate timestamps for this dates, the date function can generate actual dates.
<?php
// Array for dates
$dates = [];
// Get next thursday
$date = strtotime('thursday');
$dates[] = $date;
// Get the next four
for ($i = 0; $i < 4; $i++)
{
$date = strtotime('+1 week', $date);
$dates[] = $date;
}
// Echo dates
foreach ($dates as $date)
echo date('Y-m-d', $date);
Take a look at this post
Using that idea:
//Get First Thursday
$date = new DateTime();
$date->modify('next thursday');
echo "<br/>Starting Thursday: " . $date->format('d/m/Y');
//Loop over next 4 Thursdays
for($i = 2; $i <= 5; $i++)
{
$date->modify('+7 days');
echo "<br/>Thursday " . $i . ": " . $date->format('d/m/Y');
}

PHP Dates getting a start date and end date for each period

Okay I'm trying to generate the end of the billing period from one date; my question is if I have a variable $billing_period = 02/28/2016 and the billing periods are on every 14th and 28th of each month. from this one variable how can I generate the end date of the period when they have different days appart depending on the start date?
What's confusing to me is that if the date is the 28th it has either 15 or 16days apart from the 14th which is the start of the next billing period. And if the date is the 14th then it has 14 days apart from the 28th. Thanks for any help
EDIT
- The image here shows the date which is selected which is the 02/14/2016 how can I echo the next billing date which would be 02/28/2016 from just the start date
This is my code for the array and getting the start date.
<?
$date = array('16-01-14','16-01-28','16-02-14','16-02-28','16-03-14','16-03-28','16-04-14','16-04-28',
'16-05-14','16-05-28','16-06-14','16-06-28','16-07-14','16-07-28','16-08-14','16-08-28','16-09-14','16-09-28','16-10-14','16-10-28',
'16-11-14','16-11-28','16-12-14','16-12-28');
$currentdate = date('y-m-d');
foreach ($date as $i => $d) {
if ($currentdate >= $d && ($i == count($date)-1 || $currentdate < $date[$i+1])) {
$selected = "selected";
$selected_int = $i;
} else {
$selected = "";
}
list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
}
?>
Hope I understood well.
What you are trying to do is determine which is your billing period depending on the date you previously selected.
So, you select a date ($date).
Then you need to know the selected day
$timestamp = strtotime($date);
$day = date('D', $timestamp);
Now that you have your day you can make the comparations.
$datetime = new DateTime($date);
if ($day == 14 ){ // if you select 14th then your billing is on the 28th
$billing = $datetime->modify($date->format('Y-m-28'));
}else{ // if you didn't select 14th, then you select 28, and you add one month and set the day in 14th.
$next_month = $datetime->modify('+1 month');
$billing = $next_month->modify($date->format('Y-m-14'));
}
Build an array with the billing dates, get the current key and increment it to get the next value. Simple example with strings:
$dates = ['02/28/2016', '03/14/2016', '03/28/2016', ...];
$key = array_search( '03/14/2016', $dates );
$nextDate = $dates[$key + 1]; // 03/28/2016
Is this what you want to get?
Here the code to get you the next date, just in case you want to do it as a one off.
$date = new DateTime();
$next = $date->format('14/m/Y');
if ($date->format('d') >= 14 && $date->format('d') < 28) {
$next = $date->format('28/m/Y');
}
if ($date->format('d') >= 28) {
$date->modify('+1 month');
$next = $date->format('14/m/Y');
}
echo $next;
Here's the code turned into the function which you can call whenever you need it, it'll return a DateTime() object so you can output the date in whatever format you need at the time, or perform further comparisons/modifications should you need to down the line.
function nextBillingDate($date, $format = 'd/m/Y') {
$date = DateTime::createFromFormat($format, $date);
$next = $date->format('14/m/Y');
if ($date->format('d') >= 14 && $date->format('d') <= 28) {
$next = $date->format('28/m/Y');
}
if ($date->format('d') >= 28) {
$date->modify('+1 month');
$next = $date->format('14/m/Y');
}
return DateTime::createFromFormat('d/m/Y', $next);
}
Example use:
$date = nextBillingDate('28/02/2016');
echo $date->format('d/m/Y');
Outputs:
14/03/2016
Hope it helps.

How can I get specific dates from a number of weeks?

Using PHP, I'd like to get the dates for specific weekdays within a given number of weeks. For example, I want to get the dates for Monday, Wednesday and Friday from 10 weeks.
The pseudo code for what I want is like this:
function (monday, wednesday, friday, 10) {
// 10 is week numbers
week1 5,7,9 oct 2015
week2 12,14,16 oct 2015
...
week10
}
i write a solution for this. Thanks for all answers.
<?
$dates = array();
$i = 0;
while(true) {
$i++;
$time = strtotime("+$i days");
$dayOfWeek = date('w', $time);
if(
/*
0-sun
1-mon***
2-tue
3-wed***
4-thu
5-fri***
6-sat
*/
($dayOfWeek == 0) or
($dayOfWeek == 2) or
($dayOfWeek == 4) or
($dayOfWeek == 6)
) {
continue;
}
$dates[] = date('Y-m-d', $time);
if( count($dates) > 30 ) {
break;
}
echo json_encode($dates );
}
?>
Sounds like you want to work with schedules. I suggest you to have a look at library called When, it's "Date / Calendar recursion library for PHP 5.3+".
What you want to do is MWF schedule for next 10 weeks:
$now = new DateTime('NOW');
$after10Weeks = clone $now;
$after10Weeks->modify('+10 week');
$r = new When();
$r->startDate($now)
->freq("weekly")
->until($after10Weeks)
->byday(array('MO', 'WE', 'FR'))
->generateOccurrences();
$occurrences = $r->occurrences;
Use PHP DateTime ISO date:
$date = new DateTime(); //The object
$year=2015; // Desired year
$days = array('Mon', 'Wed', 'Fri'); // Desired days of week
for ($yearDay=1; $yearDay<=366; $yearDay++) {
$date->setISODate($year,null, $yearDay); // call ISO Date
$week=$date->format('W'); // Get the week resulted
$day=$date->format('D'); // Get the day name resulted
if($week==10 && in_array($day, $days)) // return only dates of desired days of week 10
echo $date->format('M d Y')."<br>";
}
More information about ISO Date here
You can try this code with PHPTester

Categories