How to iterate day in php? - php

I need to get the next 7 (or more) dates except sunday. Firstly i did it like
$end_date = new DateTime();
$end_date->add(new DateInterval('P7D'));
$period = new DatePeriod(
new DateTime(),
new DateInterval('P1D'),
$end_date
);
And after checked $period in foreach. But then i noticed that if i remove Sunday i need to add one more day to the end and this is each time when Sunday is... Is there any way to do it?

$start = new DateTime('');
$end = new DateTime('+7 days');
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
if ($dt->format("N") === 7) {
$end->add(new DateInterval('P1D'));
}
else {
echo $dt->format("l Y-m-d") . PHP_EOL;
}
}
See it in action

I'm a fan of using iterators, to keep the actual loop as simple as possible.
$days_wanted = 7;
$base_period = new DatePeriod(
new DateTime(),
new DateInterval('P1D'),
ceil($days_wanted * (8 / 7)) // Enough recurrences to exclude Sundays
);
// PHP >= 5.4.0 (lower versions can have their own FilterIterator here)
$no_sundays = new CallbackFilterIterator(
new IteratorIterator($base_period),
function ($date) {
return $date->format('D') !== 'Sun';
}
);
$period_without_sundays = new LimitIterator($no_sundays, 0, $days_wanted);
foreach ($period_without_sundays as $day) {
echo $day->format('D Y-m-d') . PHP_EOL;
}

You cannot remove days from a DatePeriod, but you can simply keep a count of non-Sundays and keep iterating until you have accumulated 7 of them:
$date = new DateTime();
for ($days = 0; $days < 7; $date->modify('+1 day')) {
if ($date->format('w') == 0) {
// it's a Sunday, skip it
continue;
}
++$days;
echo $date->format('Y-m-d')."\n";
}

You can try using UNIX time, adding day and if day is Sunday, add another one.
First day of your list will be eg. today at 12:00. Than you add 24 * 60 * 60 to get next day, and so on. Convert UNIX to day is simple, use date() function.
$actDay = time();
$daysCount = 0;
while(true)
{
if (date("D", $actDay) != "Sun")
{
//do something with day
$daysCount++;
}
if ($daysCount >= LIMIT) break;
$actDay += 24 * 60 * 60;
}

Related

PHP - How to get days, weeks and months without weekends?

I'm stuck in getting weeks and months using PHP's DateTime::diff function.
Here's my code:
$start = new DateTime('2017-06-05');
$end = new DateTime('2017-06-07');
$end->modify('+1 day');
$interval = $end->diff($start);
// total days
$days = $interval->days;
// create an iterateable period of date (P1D equates to 1 day)
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
// best stored as array, so you can add more than one
$holidays = array('2017-09-07');
foreach($period as $dt) {
$curr = $dt->format('D');
// substract if Saturday or Sunday
if ($curr == 'Sat' || $curr == 'Sun') {
$days--;
}
// (optional) for the updated question
elseif (in_array($dt->format('Y-m-d'), $holidays)) {
$days--;
}
}
if($days <= 7) {
echo $days." day".($days > 1 ? 's' : '');
}
// I'm stucked here
I can get the number of working days, but I can't get the months and weeks.
Somebody help me about this?
Try this code
$interval = $date1->diff($date2);
echo $interval->m // month
$week = floor($date1->diff($date2)->days/7);
echo $week; //week

Checking how many weekends are within date range

How do I check in Laravel how many Saturdays or Sundays are in given date range between $from and $to?
You can do it with plain PHP like this:
$start = new DateTime('2016-07-07');
$end = new DateTime('2016-07-27');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($start, $interval ,$end);
$saturdays = 0;
foreach($daterange as $date){
$days = $date->format('D');
if ($days == 'Sat') {
$saturdays++;
}
}
echo $saturdays;

Add the correct number of days for each month

Using the following function I can display the years and months between two dates, but how can I add the correct days for each month as another array within each month? I can't just add the days manually as I need it to account for leap years etc.
function yearMonth($start_date, $end_date)
{
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date);
$interval = new DateInterval('P1M'); // 1 month interval
$period = new DatePeriod($begin, $interval, $end);
foreach ( $period as $dt )
$years[$dt->format( "Y" )][] = $dt->format( "F" );
return $years;
}
$list = yearMonth("2007-03-24", "2009-06-26");
var_dump($list);
Since nobody else answered:
function yearMonth($start_date, $end_date)
{
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date);
$interval = new DateInterval('P1D'); // 1 month interval
$period = new DatePeriod($begin, $interval, $end);
$lastMonth = null;
$lastYear = null;
$aResult = array();
foreach ( $period as $dt )
{
if ($dt->format('Y') != $lastYear)
{
$lastYear = $dt->format('Y');
}
if ($dt->format('F') != $lastMonth)
{
$lastMonth = $dt->format('F');
}
if (!isset($aResult[$lastYear]))
{
$aResult[$lastYear] = array();
}
if (!isset($aResult[$lastYear][$lastMonth]))
{
$aResult[$lastYear][$lastMonth] = array();
}
$aResult[$lastYear][$lastMonth][] = $dt->format('d');
}
return $aResult;
}
On a side note I am planing to create a sort of Gantt chart style flat layout in table format of the years, months and days between dates. Do you think this is a suitable way of generating that? Or is there a better way?

php - check difference on dates + additional time

What would be a good way to check if point is between start and extra.
point = 2010-06-20
start = 2010-06-17
extra = start + "1 week"
Any ideas would be appreciate it.
take a look at strtotime - an then simply compare the resulting timestamps:
$start = strtotime('2010-06-20');
$point = strtotime('2010-06-17');
$extra = strtotime('+1 week', $start);
if($start < $point && $extra > $point){
// it's bewtween...
}
Requires PHP 5.3
$period = new DatePeriod(
new DateTime('2010-06-17'),
DateInterval::createFromDateString('+1 day'),
new DateTime('2010-06-17 +1 week')
);
if (in_array(new DateTime('2010-06-20'), iterator_to_array($period))) {
// date is in range
}
Manual http://de2.php.net/manual/en/dateperiod.construct.php
I'd probably extend the DatePeriod class to have a contains methods:
class DateRange extends DatePeriod
{
public function contains(DateTime $dateTime)
{
return in_array($dateTime, iterator_to_array($this));
}
}
then you can do
$period = new DateRange(
new DateTime('2010-06-17'),
DateInterval::createFromDateString('+1 day'),
new DateTime('2010-06-17 +1 week')
);
if ($period->contains(new DateTime('2011-06-20'))) {
// date is in range
}
try this
$start_timestamp = strtotime('2010-05-17');
$end_timestamp = strtotime(date("Y-m-d", $start_timestamp) . " +1 week");
$point_timestamp = strtotime('2010-16-20');
if ($point_timestamp < $end_timestamp && $point_timestamp > $point_timestamp) {
// Do your work
}

Get date range between two dates excluding weekends

Given the following dates:
6/30/2010 - 7/6/2010
and a static variable:
$h = 7.5
I need to create an array like:
Array ( [2010-06-30] => 7.5 [2010-07-01] => 7.5 => [2010-07-02] => 7.5 => [2010-07-05] => 7.5 => [2010-07-06] => 7.5)
Weekend days excluded.
No, it's not homework...for some reason I just can't think straight today.
For PHP >= 5.3.0, use the DatePeriod class. It's unfortunately barely documented.
$start = new DateTime('6/30/2010');
$end = new DateTime('7/6/2010');
$oneday = new DateInterval("P1D");
$days = array();
$data = "7.5";
/* Iterate from $start up to $end+1 day, one day in each iteration.
We add one day to the $end date, because the DatePeriod only iterates up to,
not including, the end date. */
foreach(new DatePeriod($start, $oneday, $end->add($oneday)) as $day) {
$day_num = $day->format("N"); /* 'N' number days 1 (mon) to 7 (sun) */
if($day_num < 6) { /* weekday */
$days[$day->format("Y-m-d")] = $data;
}
}
print_r($days);
The simplest method:
$start = strtotime('6/30/2010');
$end = strtotime('7/6/2010');
$result = array();
while ($start <= $end) {
if (date('N', $start) <= 5) {
$current = date('m/d/Y', $start);
$result[$current] = 7.5;
}
$start += 86400;
}
print_r($result);
UPDATE: Forgot to skip weekends. This should work now.
This is gnud's answer but as a function (also added an option to exclude the current day from the calculation):
(examples below)
public function getNumberOfDays($startDate, $endDate, $hoursPerDay="7.5", $excludeToday=true)
{
// d/m/Y
$start = new DateTime($startDate);
$end = new DateTime($endDate);
$oneday = new DateInterval("P1D");
$days = array();
/* Iterate from $start up to $end+1 day, one day in each iteration.
We add one day to the $end date, because the DatePeriod only iterates up to,
not including, the end date. */
foreach(new DatePeriod($start, $oneday, $end->add($oneday)) as $day) {
$day_num = $day->format("N"); /* 'N' number days 1 (mon) to 7 (sun) */
if($day_num < 6) { /* weekday */
$days[$day->format("Y-m-d")] = $hoursPerDay;
}
}
if ($excludeToday)
array_pop ($days);
return $days;
}
And to use it:
$date1 = "2012-01-12";
$date2 = date('Y-m-d'); //today's date
$daysArray = getNumberOfDays($date1, $date2);
echo 'hours: ' . array_sum($daysArray);
echo 'days: ' . count($daysArray);
This is OOP approach, just in case. It returns an array with all of dates, except the weekends days.
class Date{
public function getIntervalBetweenTwoDates($startDate, $endDate){
$period = new DatePeriod(
new DateTime($startDate),
new DateInterval('P1D'),
new DateTime($endDate)
);
$all_days = array();$i = 0;
foreach($period as $date) {
if ($this->isWeekend($date->format('Y-m-d'))){
$all_days[$i] = $date->format('Y-m-d');
$i++;
}
}
return $all_days;
}
public function isWeekend($date) {
$weekDay = date('w', strtotime($date));
if (($weekDay == 0 || $weekDay == 6)){
return false;
}else{
return true;
}
}
}
$d = new Date();
var_dump($d->getIntervalBetweenTwoDates('2015-08-01','2015-08-08'));

Categories