iterating through dates doesnt display the 31st of the month - php

I have this code to iterate through a month
$begin2 = new DateTime( '2017-08-01' );
$end2 = new DateTime( '2017-08-31' );
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin2, $interval, $end2);
foreach ( $period as $i ){
echo $i->format("Y-m-d")."<br/>";
}
I have also tried this:
$begin = new DateTime( '2017-08-01' );
$end = new DateTime( '2017-08-31' );
for($i = $begin; $begin <= $end; $i->modify('+1 day')){
echo $i->format("Y-m-d")."<br/>";
}
Im getting the same results for both, it skips the 31st of august, it does work with other months, Im confused and dont know what could be happening.

If you var_dump $period you see the problem.
Your end is at 31 August at 00:00.
If you set a time later on the day it will output the date.
$begin2 = new DateTime( '2017-08-01' );
$end2 = new DateTime( '2017-08-31 12:00' ); //I set the end at noon here. Any time should work except empty or 00:00
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin2, $interval, $end2);
foreach ( $period as $i ){
echo $i->format("Y-m-d")."<br/>";
}
https://3v4l.org/1n4W4

Related

PHP confusion over reversing a DatePeriod iterator

I'm trying to work out how to invert my date period without pushing the data into an array and reversing it.
Say I would like a list of the last 5 Saturdays the following code will produce:
$begin = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$begin->modify("- 4 weeks");
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1W');
$periods = new DatePeriod($begin, $interval ,$end);
foreach($periods as $date){
echo $date->format("Y-m-d") . "\n";
}
2021-07-31
2021-08-07
2021-08-14
2021-08-21
2021-08-28
I would like this list reversed. So I figured I could make use of the DatePeriod invert property. Both the start and end of the DatePeriod look correct, with a result showing in the current element. However, interating over $period returns nothing:
$begin = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$begin = $begin->modify( '+1 day' );
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end->modify("- 4 weeks");
$interval = new DateInterval('P1W');
$interval->invert = 1;
$periods = new DatePeriod($begin, $interval ,$end);
foreach($periods as $date){
echo $date->format("Y-m-d") . "\n";
}
Update
So I've found a solution that calculates a diff of days and passes that to the end param in the DatePeriod constructor. It's not ideal but is working. Note the diff->days had to be divided by the days interval to prevent additional dates pulling through.
$start = new \DateTime( date('Y-m-d', strtotime("last Saturday")));
$end = new DateTime( date('Y-m-d', strtotime("last Saturday")));
$end->modify("- 4 weeks");
$diff = $end->diff($start);
$interval = new \DateInterval('PT0S'); //0 duration
$interval->d = -7; //negative value
$period = new \DatePeriod($start, $interval, $diff->days / 7);
foreach ($period as $date) {
echo $date->format('Y-m-d') . PHP_EOL;
}

Datetime in php for-loop that is inside a foreach-loop

I have this code :
$eindejaar = date('Y-m-d', strtotime("last day of last year"));
$beginjaar = date('Y-m-d',strtotime("first day of last year"));
$begin = new DateTime( $beginjaar);
$end = new DateTime( $eindejaar );
foreach($array AS $installatie)
{
for($i = $begin; $i <= $end; $i->modify('+1 day')){
etc etc ...
Now if I initialize the datetime objects outside the foreach-loop, the for-loop goes only once.
If I place them inside the foreach-loop, it works like a charm and I get an iteratrion of the for-loop for every foreach:
$eindejaar = date('Y-m-d', strtotime("last day of last year"));
$beginjaar = date('Y-m-d',strtotime("first day of last year"));
foreach($array AS $installatie)
{
$begin = new DateTime( $beginjaar);
$end = new DateTime( $eindejaar );
for($i = $begin; $i <= $end; $i->modify('+1 day')){
etc etc ...
I can see that in the first example the datetime object $begin gets changed after 1 iteration, so that's why the second example works (I initialize it again)
Maybe a basic question, but I don't get why the object gets changed

How to include the end date in a DatePeriod?

I am trying to get a Date range for all workdays this week. I have written the following code to do so.
Code
$begin = new DateTime('monday this week'); 2016-07-04
$end = clone $begin;
$end->modify('next friday'); // 2016-07-08
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval, $end);
foreach($daterange as $date) {
echo $date->format('Y-m-d')."<br />";
}
Output
2016-07-04
2016-07-05
2016-07-06
2016-07-07
In the output friday is missing. I can fix this by doing $end->modify('next saturday') but I was wondering why the last day of a DatePeriod is not included in the range.
The iterator seems to check the time as well as the date, it excludes the end element if the time in the endDate is less that or equal to the time in the start date.
So ensure the time of the end date is at least a second greater that that of the start date.
// this will default to a time of 00:00:00
$begin = new DateTime('monday this week'); //2016-07-04
$end = clone $begin;
// this will default to a time of 00:00:00
$end->modify('next friday'); // 2016-07-08
$end->setTime(0,0,1); // new line
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval, $end);
foreach($daterange as $date) {
echo $date->format('Y-m-d')."<br />";
}
Try this code
<?php
$begin = new DateTime('2016-07-04');
$end = clone $begin;
$end->modify('next friday'); // 2016-07-08
$end->modify('+1 day');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval, $end);
foreach ($daterange as $date) {
echo $date->format('Y-m-d') . PHP_EOL;
}
In PHP 8.2 you can use DatePeriod::INCLUDE_END_DATE as constructor option!
https://www.php.net/manual/en/class.dateperiod.php#dateperiod.constants.include-end-date

Add datetime Value

I'm searching for the best way to echo day numbers in a week.
First i need to check what week there is.
And then echo all dates of the week into variables.
This is what i got:
//This Week Variable dates
$this_year = date('Y');
$this_week_no = date('W');
$this_week_mon = new DateTime();
$this_week_mon->setISODate($this_year,$this_week_no);
How do i rise tue by one day?
$this_week_tue = $this_week_mon ++;
You can use DateTime::modify():
$this_week_mon->modify('+1 day');
or DateTime::add() which accepts a DateInterval() object:
$this_week_mon->add(new DateInterval('P1D'));
You can loop through all of the days of the week using DatePeriod():
$start = new DateTime();
$start->setISODate($this_year,$this_week_no);
$end = clone $start;
$end->modify('+1 week');
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
echo $date->format('N');
}
$this_week_mon->modify('+1 day');
Should increment $this_week_mon by one day. To increase by more, just use days;
$this_week_mon->modify('+27 day');
Would increment by 27 days.

Include last date in range between dates in php

I have found a problem with using DatePeriod which might be because I am stupid lol.
As you can see I have added +1 to my end date because I want to include the last date of the range.
But my issue is when I have ending date 31 it makes it to 32 which is not a date so it throws out an error.
Is there a way to include the ending date or to make the +1 work?
$period = new DatePeriod(
new DateTime($event['startyear'].$event['startmonth'].$event['startdate']),
new DateInterval('P1D'),
new DateTime($event['endyear'].$event['endmonth'].$event['enddate'] +1)
);
foreach ($period as $savedDate) {
echo $savedDate;
}
You should create the date object for the initial date (without the +1) and then increment the day of that object by 1 day.
For example:
$date1 = new DateTime($event['endyear'].$event['endmonth'].$event['enddate']);
$date2 = new DateTime($event['endyear'].$event['endmonth'].$event['enddate']);
$date2->modify('+1 day');
$period = new DatePeriod($date1, new DateInterval('P1D'), $date2);
What about this:
$endDate = mktime(0,0,0, $event['endmonth'], $event['enddate'], $event['endyear']);
$counter = 0;
while($endDate >= $date = mktime(0,0,0, $event['startmonth'], $event['startdate']+$counter++, $event['startyear']) ) {
echo date('Y/m/d', $date);
}

Categories