How to loop through months of a PHP DatePeriod class? - php

I need to get all the numeric months spanned by a date range. So for a range 18 Jul 2014 - 4 Sep 2014, give me 7,8,9.
This is getting me close:
$start = new DateTime('2014-07-18');
$interval = new DateInterval('P1M');
$end = new DateTime('2014-09-04');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format('n') . PHP_EOL;
}
It returns 7 and 8, but no 9 for September because it's not a full P1M interval. I'd like to get 7,8,9 regardless of where the start/end days fall in the month.
Am I going in the right direction?

Found an answer on this page: http://forums.phpfreaks.com/topic/275341-find-what-months-a-date-range-covers/
$start = new DateTime('2014-07-18');
$end = new DateTime('2014-09-04');
$inc = DateInterval::createFromDateString('first day of next month');
$end->modify('+1 day');
$p = new DatePeriod($start,$inc,$end);
foreach ($p as $d)
echo $d->format('n') . PHP_EOL;
Outputs:
7 8 9

Related

get time intervals with time range

I am trying to get time interval with custom start and end time variables for which i have searched and find its relevant information on this link.
I have tried the following code but its giving errorUncaught Error: Call to a member function date() on string
$start = date("H:i",strtotime('08:30 AM'));
$end = date("H:i",strtotime('06:00 PM'));
for($i = $start; $i <= $end; $i->modify(' +30 MINUTE')){
echo $i->date("H:i");
}
You need to use the builtin \DateTime class and the \DateInterval class as well
$begin = new DateTime('08:30:00');
$end = new DateTime('12:45:00');
$interval = DateInterval::createFromDateString('30 minute');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("H:i\n");
}
RESULTS
08:30
09:00
09:30
10:00
10:30
11:00
11:30
12:00
12:30
And if the time roles over to another day something like this
$begin = new DateTimeImmutable('2022-03-01 16:00:00');
$end = (new DateTime())->createFromImmutable($begin)->add(new DateInterval('P1D'))->settime(8,30,0);
$interval = DateInterval::createFromDateString('30 minute');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("d/m/Y H:i\n");
}

Get total number of days every 6 months from given total number of years or months

I need to get the total number of days every 6 months from the given total number of days.
So far this is what I achieved.
$begin = new DateTime( '2019-08-31' );
$end = new DateTime( '2020-08-31' );
// get interval in months
$interval1 = DateInterval::createFromDateString('6 month');
$period = new DatePeriod($begin,$interval1,$end);
$counter = 0;
foreach($period as $date){
$counter++;
}
echo "counter:".$counter."<br>";
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
$count = 0;
foreach($daterange as $date){
//echo $date->format("Ymd") . "<br>";
$count++;
}
echo "<br>count:".$count;
for($i=1;$i<=$counter;$i++){
}
Actual result:
counter:2
count:366
What I want to achieve:
counter:2
count:366
result:182 // for the first 6 months
result:184 // for the next 6 months
For add month, a start date with day = 31 is a problem. Datetime adds 6 month like this:
echo date_create("2019-08-31")
->modify("+6 Month")
->format("Y-m-d")
; //2020-03-02
If the start is at the beginning of a month, the solution is simple.
With DateTime::diff the difference can be calculated in full days.
$begin = new DateTime( '2019-08-01' );
$end = new DateTime( '2020-08-01' );
$interval = "6 Month";
$counter = 0;
while($begin < $end){
$curStart = clone $begin;
$begin->modify($interval);
$diffDays = $curStart->diff($begin)->days;
echo $curStart->format("Y-m-d")." - ".$begin->format("Y-m-d");
echo ": ".$diffDays." Days<br>";
}
Outputs
2019-08-01 - 2020-02-01: 184 Days
2020-02-01 - 2020-08-01: 182 Days

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: Loop through all weeks in a date range (last 2 years)?

I like to iterate through all weeks in a date range that spawns 2 years. Starting at the current week number two years ago, until the current week number this year.
The problem is that a year can either have 52 weeks or 53 weeks, for example:
2015 had 53 weeks (the 53th was from 2015-12-28 till 2016-01-03)
2016 had 52 weeks (the 52th was from 2016-12-26 till 2017-01-01)
So this is currently my php code:
# start with the current week 2 years ago
$year = date("Y") - 2;
$week = (int) date("W"); // (int) removes leading zero for weeks < 10
$endYear = date("Y");
$endWeek = (int) date("W");
# iterate through all weeks until now
do {
echo $week. " of ". $year;
$week++;
if ($week > 52) { // or greater 53 ?????????????
$year ++;
$week = 1;
}
}
while ($year < $endYear || $week < $endWeek);
Instead of trying to keep track of the bounds, let PHP do it for you.
$start = new DateTime('-2 years');
$end = new DateTime();
$interval = new DateInterval('P1W');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
echo $date->format('W') . " of ". $date->format('Y') . "\n";
}
Demo
With the help of Ross Wilson and John Conde I found a solution:
$now = new DateTime;
$from = (new DateTime)->setISODate($now->format('Y') - 2, $now->format('W'));
$from->modify("thursday this week"); // see ISO 8601
while($from < $now) {
echo $from->format('W Y').'<br />';
$from->modify("+1 week");
}
It is important so set the week day to thursday, because according to ISO 8601, the week "belongs" to the year which still contains the thursday.
You could use DateTime and setISODate for something like this:
$now = new DateTime;
$from = (new DateTime)->setISODate($now->format('Y') - 2, $now->format('W'));
while($from < $now) {
echo $from->format('W Y').'<br />';
$from->modify("1 week");
}
Hope this helps!

List all the years between dates

I am looking to list every year between dates using PHP and Mysql data base, the code is this:
<?php
$start = new DateTime('2010-12-02');
$start->modify('first day of this month');
$end = new DateTime('2016-05-06');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 year');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y") . "<br>\n";
}
?>
Output
2010
2011
2012
2013
2014
2015
Missing the year 2016.
How I can do to make 2016 also returns? It should return as it does to 2010
$start = '2010-12-02';
$end = '2016-05-06';
$getRangeYear = range(gmdate('Y', strtotime($start)), gmdate('Y', strtotime($end)));
print_r($getRangeYear);
use the range function to get list of ranging numbers, first parameter start range, and second ending range..
http://php.net/manual/en/function.range.php
It is simple: you are iterating between 2010-12-02 and 2016-05-06. The generated dates are:
2010-12-02 -> ok
2011-12-02 -> ok
2012-12-02 -> ok
2013-12-02 -> ok
2014-12-02 -> ok
2015-12-02 -> ok
2016-12-02 -> over 2016-05-06 - stop algorithm.
I do not know exactly what do you want to do, but it seem that you should change end date.
<?php
$start = new DateTime('2010-12-02')->modify('+1 year');
$start->modify('first day of this month');
$end = new DateTime('2016-05-06');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 year');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y") . "<br>\n";
}
?>

Categories