PHP confusion over reversing a DatePeriod iterator - php

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;
}

Related

iterating through dates doesnt display the 31st of the month

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

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

How to divide datetime period into separate days in PHP

I need to divide time period for example from:
2015-11-22 11:22:33 to 2015-11-24 02:02:04
into something like this:
2015-11-22 11:22:33 - 2015-11-22 23:59:59
2015-11-23 00:00:00 - 2015-11-23 23:59:59
2015-11-24 00:00:00 - 2015-11-24 02:02:04.
It has to work also for periods shorter than 24h, so for
2015-11-22 11:22:33 to 2015-11-23 02:02:04
I need this:
2015-11-22 11:22:33 - 2015-11-22 23:59:59
2015-11-23 00:00:00 - 2015-11-23 02:02:04.
I found almost perfect piece of code, but it only works for periods longer than 24h and I don't know how to tune it.
<?php
$start_date = '27:04:2013';
$start_time = '16:30';
$end_date = '29:04:2013';
$end_time = '22:30';
// Date input strings and generate a suitable DatePeriod
$start = DateTime::createFromFormat("d:m:Y H:i", "$start_date $start_time");
$end = DateTime::createFromFormat("d:m:Y H:i", "$end_date $end_time");
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
// Get midnight at start of current day
$date_start = clone $date;
$date_start->modify('midnight');
// Get 23:59:59, end of current day
// (moving to midnight of next day might be good too)
$date_end = clone $date;
$date_end->modify('23:59:59');
// Take care of partial days
$date_start = max($start, $date_start);
$date_end = min($end, $date_end);
// Here you would construct your array of
// DateTime pairs, or DateIntervals, as you want.
printf(
"%s -> %s \n",
$date_start->format('Y-m-d H:i'),
$date_end->format('Y-m-d H:i')
);
}
?>
Try this:
$date1 = '2015-11-22 11:22:33';
$date2 = '2015-11-23 12:22:34';
$f1 = strtotime($date1);
$f2 = strtotime(substr($date1, 0, 10) . " 23:59:59");
while($f2 < strtotime($date2)) {
print(date('Y-m-d H:i:s',$f1) .' - ' .date('Y-m-d H:i:s',$f2).'<br>');
$f1 = strtotime(date('Y-m-d H:i:s', $f2) .' +1 second');
$f2 = strtotime(date('Y-m-d H:i:s', $f2) .' +1 day');
}
print(date('Y-m-d H:i:s',$f1) .' - ' .$date2.'<br>');
See here: http://sandbox.onlinephpfunctions.com/code/77eaae15fdd7c0d2ca1f02a2d225c17199218819
$datetime1 = new DateTime('2015-11-22 11:22:33');
$datetime2 = new DateTime('2015-11-23 02:02:04');
$interval = $datetime1->diff($datetime2);
var_dump($interval->format('%y-%m-%d %h:%i:%s'));
// RESULT: string(14) "0-0-0 14:39:31"
References:
http://php.net/manual/de/datetime.diff.php
http://php.net/manual/de/class.dateinterval.php
http://php.net/manual/de/dateinterval.format.php

php get today tomorrow and next day but ignore weekends

How can I get the current day, tomorrow and next day in PHP but ignore weekends?
I have already tried this code, but it will include Saturday and Sunday.
array(
'todayDate' => date('d/m/Y')
'tomorrowDate' => date('d/m/Y', strtotime(' +1 day')),
'nextDay' => date('l', strtotime(' +2 day'))
)
Thanks.
Use Weekday(s) with strtotime
date('l', strtotime(' +2 Weekdays'));
Fiddle
This finds the next weekday from a specific date (not including Saturday or Sunday):
echo date('Y-m-d', strtotime('2011-04-05 +2 Weekday'));
You could also do it with a date variable of course:
$myDate = '2011-04-05';
echo date('Y-m-d', strtotime($myDate . ' +2 Weekday'));
Try this, Get date between two date without weekdays(Saturday and Sunday).
$startdate = '10-06-2015';
$endDate = '17-06-2015' ;
$Workingdays = getdateBettwoDate($startdate,$endDate);
print_r($Workingdays);
function getdateBettwoDate($startdate,$enddate)
{
$start = new DateTime($startdate);
$end = new DateTime($enddate);
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
$x=0;
$a=array();
foreach ($period as $dt)
{
$temp=$dt->format("l d-m-Y");
$ArTemp=explode(' ',$temp);
if($ArTemp[0]=='Saturday' || $ArTemp[0]=='Sunday'){
}else{
$a[$x]=$ArTemp[1];
$x++ ;
}
}
$a[$x]=date('l', strtotime( $enddate))." ".$enddate;
return $a ;
}

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.

Categories