Stepping back in DatePeriod loop - php

As I understand I can't set the foreach loop back by variable steps, so I use a for loop like this:
$beginDate = new DateTime( $firstday );
$endDate = new DateTime( $lastday );
$endDate = $endDate->modify( '+1 day' );
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($beginDate, $interval, $endDate);
$datesArray=array();
foreach($period as $dt) $datesArray[]=$dt->format('Y-m-d');
for ($dateindex=0; $dateindex < count($datesArray); $dateindex++) {
...
Is there a better way to do this?

yes, use
$interval = DateInterval::createFromDateString('-1 day');
then work out the difference in days between $endDate and $beginDate, and use that difference in your loop:
$beginDate = new DateTime('2016-11-28');
$endDate = new DateTime('2016-12-07');
$endDate = $endDate->modify( '+1 day' );
$interval = DateInterval::createFromDateString('-1 day');
$diff = $endDate->diff($beginDate);
$period = new DatePeriod($beginDate, $interval, $diff->days);
$datesArray=array();
foreach($period as $dt) $datesArray[]=$dt->format('Y-m-d');
var_dump($datesArray);

Related

How to get Months between two dates

I'm trying to get All the months between two dates.
for e.g if the user posted an article on 21-10-2012 and today date is 5-12-2017. Now i want to get all the month and Year between this period like shown below
10-2012
11-2012
01-2013
02-2014
03-2015
04-2015
05-2015
06-2015
07-2015 // and so on
.......
.......
.......
12-2017 // Till Today Date
Till Now i was only able to calculate the difference.
$article_date= date("d-m-Y", $article['date']);
$year = date("Y");
$month = date("m");
$day = date("d");
$date1 = new DateTime($article_date);
$date2 = new DateTime("$day-$month-$year");
$diff = $date1->diff($date2);
echo (($diff->format('%y') * 12) + $diff->format('%m')) . " full months difference";
How can i get all the months?
Use this code
$start = new DateTime('2012-10-21');
$start->modify('first day of this month');
$end = new DateTime('2017-12-05');
$end->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("m-Y") . "<br>\n";
}
function list_months($date_from,$date_to, $return_format){
$arr_months = array();
$a = new \DateTime($date_from);
$x = new \DateTime($date_to);
$start = $a->modify('first day of this month');
$end = $x->modify('first day of next month');
$interval = \DateInterval::createFromDateString('1 month');
$period = new \DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
$arr_months[] = $dt->format($return_format);
}
return $arr_months ;
}
Example: $new_list = list_months('11-10-2012','11-10-2017', 'm-Y');

Get all dates from last 30 days (datetime objects)

I am trying to get an array of datetime objects but failing miserably.
I want to take today's date, and get all dates within the last 30 days.
$today = new DateTime();
$begin = $today->sub(new DateInterval('P30D'));
$interval = new DateInterval('P1D'); // 1 Day
$dateRange = new DatePeriod($begin, $interval, $today);
$range = [];
foreach ($dateRange as $date) {
$range[] = $date->format('Y-m-d');
}
When I dump out $range, I get an empty array.
What am I doing wrong?
Change
$begin = $today->sub(new DateInterval('P30D'));
to
$begin = new DateTime();
$begin->sub(new DateInterval('P30D'));
the "sub" method modifies the source object, as well as outputting the object itself as the return value (really this is intended for method chaining). It doesn't just create a new object with the new date.
$begin = $today->sub(new DateInterval('P30D'));
modifies $today as well as outputting a copy which you then declare as $begin. This results in both objects having the same date, and thus there's no time interval over which to iterate.
See http://php.net/manual/en/datetime.sub.php
You need to create a separate object for your end date:
$begin = new DateTime();
$begin->sub(new DateInterval('P30D'));
$end = new DateTime();
$interval = new DateInterval('P1D'); // 1 Day
$dateRange = new DatePeriod($begin, $interval, $end);
$range = [];
foreach ($dateRange as $date) {
$range[] = $date->format('Y-m-d');
}
var_dump($range);
See it working at https://eval.in/867948
you overwrite $today so $today and $begin is exactly the same
$today = new DateTime();
$copy = clone $today;
$begin = $copy->sub(new DateInterval('P30D'));
$interval = new DateInterval('P1D'); // 1 Day
$dateRange = new DatePeriod($begin, $interval, $today);
$range = [];
foreach ($dateRange as $date) {
$range[] = $date->format('Y-m-d');
}
will work

Get years and month between two dates

I am trying this code:
$start_date = "2015-08-19";
$end_date = "2016-02-19";
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date);
$interval = new DateInterval('P1Y'); // 1 Year interval
$period = new DatePeriod($begin, $interval, $end);
foreach ( $period as $dt ){
echo $dt->format( "Y" );
}
$intervals = new DateInterval('P1M'); // 1 month interval
$periods = new DatePeriod($begin, $intervals, $end);
foreach ( $periods as $dts ){
echo $dts->format( "m" );
}
I'm getting output like this:
year:2015
Month:08,09,...,01
In this output I'm not getting year:2016 and month:02. I want my output like this:
year:2015,2016
Month:08,09,...,01,02
How can I get this?
And if my end date is "2016-08-20"
than i m getting year:2016 but not getting month :08
Note that my start date and end date is not fixed.
As mentioned before, the end date is not included
You may also modify the end date like that
$end = $end->modify( '+1 day +1 year' );
See php's DateTime modify for more info.
Update
If end year is more than 1 year bigger than the begin date then adding a year will indeed return a year more than what we want.
A solution is to check and add the year only if is needed like that:
if($begin > (new DateTime( $end_date))->modify('-1 year')) {
$end->modify( '+1 year' );
}
$end->modify('+1 day');
You can use the following code to achieve this:
<?php
$start = (new DateTime('2015-12-02'))->modify('first day of this month');
$end = (new DateTime('2016-05-06'))->modify('first day of this month');
//For Year
$interval = DateInterval::createFromDateString('1 year');
$period = new DatePeriod($start, $interval, $end);
echo 'Year: ';
foreach ($period as $dt)
{
echo $dt->format("Y") . ",";
}
//For Month
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
echo '<br/>Month: ';
foreach ($period as $dt)
{
echo $dt->format("m") . ",";
}
?>
Alternatively, you can display it nicely in Y-m format by the following code:
$start = (new DateTime('2015-12-02'))->modify('first day of this month');
$end = (new DateTime('2016-05-06'))->modify('first day of this month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt)
{
echo $dt->format("Y-m") . "<br>\n";
}
since the year 2016 and the month 02 is not completed you are not getting it.
try this
$start_date = "2015-08-19";
$end_date = "2016-02-19";
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date);
$end->add(new DateInterval('P1Y1M'));
$interval = new DateInterval('P1Y'); // 1 Year interval
$period = new DatePeriod($begin, $interval, $end);
foreach ( $period as $dt ){
echo $dt->format( "Y" );
}
$intervals = new DateInterval('P1M'); // 1 month interval
$periods = new DatePeriod($begin, $intervals, $end);
foreach ( $periods as $dts ){
echo $dts->format( "m" );
}

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 Day iterator

I'm able to show days from current date to next 3 months with this code:
$begin = new DateTime();
$end = new DateTime(date('Y-m-d', strtotime('+3 months', strtotime(date("d-m-Y")))));
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
foreach ( $days as $day ) {
...
}
I feel the code can be shortened especially for $end. Could you help?
Oh, I also want to get previous 3 months. I changed '+3 months' to '-3 months'but no luck. Any ideas?
$begin = new DateTime();
$end = new DateTime('+ 3 months');
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
foreach ( $days as $day ) {
var_dump($day);
}
$begin = new DateTime('- 3 months'); // '3 months ago' should also work
$end = new DateTime();
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
foreach ( $days as $day ) {
var_dump($day);
}
For your first question, you can directly write
$end = new DateTime('+3 months');
To go back 3 months, use3 months ago instead of -3 months.

Categories