This question already has answers here:
Get the last 12 months in PHP
(5 answers)
Closed 3 years ago.
I'm trying to use a loop to show the last 12 months, but March appears twice.
for ($i=0; $i < 12; $i++) {
$month = date("d/m/Y", strtotime("now -$i month"));
echo "$month<br>";
}
Output:
30/01/2020
30/12/2019
30/11/2019
30/10/2019
30/09/2019
30/08/2019
30/07/2019
30/06/2019
30/05/2019
30/04/2019
30/03/2019
02/03/2019
How can I solve this?
Use the first day of the month as the basis in your script.
"first day of this month -$i month"
Use DateTime and keep track of month/year combinations that you already had:
$dt = new DateTime();
$previous = [];
for ($i=0; $i < 12; $i++) {
$month = $dt->format("d/m/Y");
echo "$month<br>".PHP_EOL;
$previous[$dt->format('Y-m')] = true;
$dt->modify('-1 month');
while (array_key_exists($dt->format('Y-m'), $previous)) {
$dt->modify('-1 day');
}
}
If this encounters a previously encountered month-year combination, it starts substracting days until it reaches the previous month.
Will produce this output:
30/01/2020
30/12/2019
30/11/2019
30/10/2019
30/09/2019
30/08/2019
30/07/2019
30/06/2019
30/05/2019
30/04/2019
30/03/2019
28/02/2019
You probably want to use DatePeriod for this task and not date. It's much simpler and more sane.
$start = new DateTime;
$start->setDate($start->format('Y'), $start->format('n'), 1); // Normalize the day to 1
$start->sub(new DateInterval('P12M'));
$interval = new DateInterval('P1M');
$recurrences = 12;
foreach (new DatePeriod($start, $interval, $recurrences, true) as $date) {
echo $date->format('F, Y'), "\n"; // attempting to make it more clear to read here
}
Output:
February, 2019
March, 2019
April, 2019
May, 2019
June, 2019
July, 2019
August, 2019
September, 2019
October, 2019
November, 2019
December, 2019
January, 2020
Related
How can I loop the year and months with some given dates?
Below is my current code and I can't get it running
$Startdate = '2017-01';
$Enddate = '2018-06';
for($selectedDate = date("Y-m",$begin); $selectedDate <= date("Y-m",$end); $selectedDate++){
$resultY = date("Y",strtotime($selectedDate));
$resultM = date("m",strtotime($selectedDate));
echo $resultY;
$echo resulthM;
}
The output should be:
2017 1
2017 2
2017 3
2017 4
2017 5
2017 6
2017 7
2017 8
2017 9
2017 10
2017 11
2017 12
2018 1
2018 2
2018 3
2018 4
2018 5
2018 6
If I were you :) I will try with DateTime class to generate months between your $Startdate and $Enddate. See DateTime
<?php
$start = new DateTime('2017-01');
$end = new DateTime('2018-06');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
echo $dt->format("Y-m") . PHP_EOL;
}
DEMO: https://3v4l.org/FvmS4
Since you were familiar with strtotime, you can amend your code to the following to execute the desired results.
$begin = date("Y-m", strtotime("2017-01")); // Replace this with date to begin.
$end = date("Y-m"); // Replace this with date to end.
for($selectedDate = date("Y-m", strtotime($begin)); $selectedDate <= date("Y-m", strtotime($end)); $selectedDate = date("Y-m", strtotime($selectedDate . "+1 Month"))){
$resultY = date("Y", strtotime($selectedDate));
$resultM = date("m", strtotime($selectedDate));
echo $resultY;
echo $resultM;
}
However, equally, user don't angry me, has an answer that will allow you to use the DateTime objects and manipulate them instead, so if you'd rather switch over your code to something potentially more reliable, you could do that also.
$startDate = new \DateTime('2017-01-01');
$endDate = new \DateTime('2018-06-01');
for($selectedDate = $startDate; $selectedDate <= $endDate; $selectedDate->modify('+1 month')) {
// format $selectedDate;
$resultY = $selectedDate->format('Y');
$resultM = $selectedDate->format('m');
// print content
echo $resultY;
echo "\t"; // print tab
echo $resultM;
echo "\n"; // print new line
}
You can use DateTime::modify and walk the months forward
$Startdate = '2017-01';
$Enddate = '2018-06';
$DateTime = new DateTime($Startdate.'-01');
echo $DateTime->format('Y')."\t".$DateTime->format('n')."\n";
do{
$DateTime->modify('+1 months');
echo $DateTime->format('Y')."\t".$DateTime->format('n')."\n";
if($DateTime->format('Y-m') == $Enddate) break;
}while(true);
Just make sure the Enddate is a valid Year/Month and happens after Startdate or in this example you'll loop forever.
There are probably other ways to do the loop that avoids that.
But I didn't see DateTime::modify used in an answer so I thought I would throw one together.
Output:
2017 1
2017 2
2017 3
2017 4
2017 5
2017 6
2017 7
2017 8
2017 9
2017 10
2017 11
2017 12
2018 1
2018 2
2018 3
2018 4
2018 5
2018 6
Sandbox
I usually use this method when I want to make a select/option for stuff like months. But I use this format str_pad($DateTime->format('n'),2,' ',STR_PAD_LEFT).' - '.$DateTime->format('F') OR ' 2 - February', notice the space on the left ... :) ... that way they all line up nice and neat like.
Anyway, cheers!
There is this Unix timestamp and it needs to generate the first days of the week as an array.
$time = '1456034400';
// This present Month February 2016
// in calendar the February has the start of the week
// Sunday 7
// Sunday 14
// Sunday 21
// Sunday 28
How do you get an array like this from the Unix Timestamp:
$weekdays = array(
0 => 7,
1 => 14,
2 => 21,
3 => 28
);
And this method needs to work and be accurate for any given month in years not just Feb 2016.
function getSundays($y, $m)
{
return new DatePeriod(
new DateTime("first Sunday of $y-$m"),
DateInterval::createFromDateString('next sunday'),
new DateTime("last day of $y-$m")
);
}
$days="";
foreach (getSundays(2016, 04) as $Sunday) {
$days[] = $Sunday->format("d");
}
var_dump($days);
https://3v4l.org/DVYM5
A bit faster way (since it uses a simple calculation to iterate weeks):
$time = 1456034400;
$firstDay = strtotime('first Sunday of '.date('M',$time).' '.date('Y',$time));
$lastDay = mktime(0,0,0,date('m',$time)+1,1,date('Y', $time));
$weekdays = array();
for ($i = $firstDay; $i < $lastDay; $i += 7*24*3600){
$weekdays[] = date('d',$i);
}
https://3v4l.org/lQkB2/perf#tabs
I'm looking to find the date of the 29th of this month, the 29th of next month, the 29th of last month and so on...
I know you can use this kind of code to find days of the week:
$friday_last = date("d/m/Y", strtotime("last Friday"));
$friday_due = date("d/m/Y", strtotime("this Friday"));
Is there a similar way to find a certain day (29th) of each month or would I have to use a different code?
You need to use DateTime() as it makes working with dates much easier. You'll notice I start by going to the first day of each month. That's so this doesn't break when you get to the 29th-30th of each month as weird date things start to happen.
echo (new DateTime())->modify('first day of this month')->format("29/m/Y");
echo (new DateTime())->modify('first day of previous month')->format("29/m/Y");
echo (new DateTime())->modify('first day of next month')->format("29/m/Y");
Demo
echo (new DateTime())->modify('first day of this month')->modify('-2 months')->format("29/m/Y");
Demo
Using date() with strtotime() will gives you 29th from each month within this year:
<?php
for ($i = 1; $i <= 12; $i++) {
$d = "2016-" . $i . "-29";
echo "29th of Month $i is: " . date("l", strtotime($d)) . '<br>';
}
?>
Output:
29th of Month 1 is: Friday
29th of Month 2 is: Monday
29th of Month 3 is: Tuesday
29th of Month 4 is: Friday
29th of Month 5 is: Sunday
29th of Month 6 is: Wednesday
29th of Month 7 is: Friday
29th of Month 8 is: Monday
29th of Month 9 is: Thursday
29th of Month 10 is: Saturday
29th of Month 11 is: Tuesday
29th of Month 12 is: Thursday
To create an array with current and next 11 months 29th day (for previous months replace +1 month with -1 month. In this example I use +1 to explain february issue, that is not present in past february):
$baseDate = date_create()->modify( 'first day of this month' );
$dates = array();
for( $i = 0; $i<12; $i++ )
{
$newDate = clone $baseDate;
$dates[] = $newDate->modify( '+28 days' );
$baseDate->modify( '+1 month' );
}
The problem — as you can imagine — is with february:
foreach( $dates as $date )
{
echo $date->format( 'Y-m-d' ).PHP_EOL;
}
Will output:
2016-05-29
2016-06-29
2016-07-29
2016-08-29
2016-09-29
2016-10-29
2016-11-29
2016-12-29
2017-01-29
2017-03-01 <-----
2017-03-29
2017-04-29
If you want a result like “29th month's day OR last month's day” modify above for loop in this way:
for( $i = 0; $i<12; $i++ )
{
$newDate = clone $baseDate;
if( $newDate->modify( '+28 days' )->format( 'm' ) != $baseDate->format( 'm' ) )
{
$newDate->modify( 'last day of previous month' );
}
$dates[] = $newDate;
$baseDate->modify( '+1 month' );
}
Result:
2016-05-29
2016-06-29
2016-07-29
2016-08-29
2016-09-29
2016-10-29
2016-11-29
2016-12-29
2017-01-29
2017-02-28 <-----
2017-03-29
2017-04-29
I'm not sure when this started, but now you can do so by using just date() and strtotime(), like this:
$d = date("Y-m-d 00:00:00", strtotime('first day of 2 months ago'));
$l = date("Y-m-d 00:00:00", strtotime('last day of 2 months ago'));
print_r($d);
print_r($l);
Assuming today (2023-02-01) The above will display:
2022-12-01 00:00:00
2022-12-31 00:00:00
Sample:
https://onlinephp.io/c/db73f
I want to populate a select input with the last 5 months (including the current month). So on 09/04/2014 the options should look something like this:
April 2014
March 2014
February 2014
January 2014
December 2013
My first solution with PHP DateTime seemed to work:
for ($i = 0; $i < 5; $i++) {
$date = new DateTime($i.' months ago');
echo $date->format('F Y'); //populate select input
}
But in fact it doesn't handle edge cases. For example, on 31/03/2014 it produces:
March 2014
March 2014
January 2014
December 2013
December 2013
What is the correct way to list the last 10 months with PHP DateTime?
$date = new DateTime("2014/03/31");
for ($i = 0; $i <= 9; $i++) {
$date->modify("-1 month");
echo $date->format('F Y'); //populate select input
}
You are getting same 2 months, because when you are subtracting 1 month from date, that has more days than previous month. Example: when you subtract 1 month from 31.3. you will get 3.3. (same month), and not 28.2. as you might expect...
My suggestion is to get first day of current month, and then do your logic:
$dt = new DateTime('first day of this month');
for ($i = 1; $i <= 10; $i++) {
echo $dt->format('F Y'), "\n";
$dt->modify('-1 month');
}
demo
This question already has answers here:
PHP: Populating an array with the names of the next 12 months
(8 answers)
Closed 8 years ago.
I've done some research over internet and i cannot find the right answer that closes to my problem. I'm just beginner in php and I don't understand advance programming yet. My problem is I want to get the current date in next month.
suppose:
today is Feb 15 2014,
I want to get date
March 15 2014,
April 15 2014,
May 15 2014,
June 15 2014,
July 15 2014,
August 15 2014,
September 15 2014,
October 15 2014,
November 15 2014,
December 15 2014,
January 15 2015, and so on and so fourth.
$new_date = date('F d Y', strtotime('+1 month'));
or
for ($i = 1; $i <12; $i++){
$new_date = date('F d Y', strtotime("+$i month"));
echo $new_date;
}
Here is another solution:
$begin = new DateTime( '2014-03-15' );
$end = new DateTime( '2015-01-31' );
$interval = new DateInterval('P1M');
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date){
echo $date->format("F d Y") . "<br>";
}
or this if you want to do it without a end date:
$date= new DateTime( '2014-03-15' );
for($i = 1; $i < 10; $i++) {
$date = $date->modify( '+1 month' );
echo $date->format("F d Y") . "<br>";
}