Getting the First Sunday in any Given Year in PHP [duplicate] - php

I need to use PHP DateTime to get the first day of the current year. I've tried:
$year = new DateTime('first day of this year');
var_dump($year);
But this seems to be returning the first day of the current month: 2014-09-01 09:28:56
Why? How do I correctly get the first day of the current year?

Your relative date format 'first day of this year' is correct by returning the first day of the month because of the definition of first day of:
Sets the day of the first of the current month. This phrase is best
used together with a month name following it. (See PHP-doc)
To get the first day of the current year with the relative format you can use something like this:
'first day of January ' . date('Y')

Or use only text in the strtotime function:
date('Y-m-d', strtotime('first day of january this year'));

echo date('l',strtotime(date('Y-01-01')));

You can get the current date and then set day and month to 1:
$year = new DateTime();
$year->setDate($year->format('Y'), 1, 1);
Optionally, you can set the time to midnight:
$year->setTime(0, 0, 0);

If you want to get first day of current year just use this code
echo date("l", strtotime('first day of January '.date('Y') ));

Just wanted to record some nuance with the answer by lorem monkey
The suggested method might cause issues with when using time zones.
scenario: consider current system time is 2018-01-01 00:20:00 UTC and system default time zone is set to UTC.
date('Y') will give you 2018
if you are doing something like:
$startDate = new DateTime('first day of january '.date('Y'), new DateTimeZone('America/New_York'));
This will compute to 'first day of january 2018' but you actually needed the first date of your current year in America/New_York, which is still 2017.
Stop dropping the ball man, its not new year yet!
So it is better to just do
$startDate = new DateTime('first day of january', new DateTimeZone('America/New_York'));
And then do the modifications as needed by using the DateTime::modify() function.
Relative date formats are fun.
My scenario: I wanted to get the bounds of this year as in 2018-01-01 00:00:00 to 2018-12-31 23:59:59
This can be achieved in two ways with relative date formats.
one way is to use the DateTime::modify() function on the object.
$startDate = (new DateTime('now', new DateTimeZone("America/New_York")));
$endDate = (new DateTime('now', new DateTimeZone("America/New_York")));
$startDate->modify("january")
->modify("first day of this month")
->modify("midnight");
$endDate->modify("next year")
->modify("january")
->modify("first day of this month")
->modify("midnight")->modify("-1 second");
var_dump([$startDate, $endDate]);
Try out here: https://www.tehplayground.com/Qk3SkcrCDkNJoLK2
Another way to do this is to separate the relative strings with a comma like so:
$startDate = (new DateTime('first day of january', new DateTimeZone("America/New_York")));
$endDate = (new DateTime('next year, first day of january, -1 second', new DateTimeZone("America/New_York")));
var_dump([$startDate, $endDate]);
Try out here: https://www.tehplayground.com/hyCqXLRBlhJbCyks

Basically date('Y') returns the value of current year. and the first day of each year starts like 2000-01-01.
So this will help you to get exact output.
$firstdate = date( 'Y' ) . '-01-01';

Take a look at this link -- http://davidhancock.co/2013/11/get-the-firstlast-day-of-a-week-month-quarter-or-year-in-php/
function firstDayOf($period, DateTime $date = null)
{
$period = strtolower($period);
$validPeriods = array('year', 'quarter', 'month', 'week');
if ( ! in_array($period, $validPeriods))
throw new InvalidArgumentException('Period must be one of: ' . implode(', ', $validPeriods));
$newDate = ($date === null) ? new DateTime() : clone $date;
switch ($period) {
case 'year':
$newDate->modify('first day of january ' . $newDate->format('Y'));
break;
case 'quarter':
$month = $newDate->format('n') ;
if ($month < 4) {
$newDate->modify('first day of january ' . $newDate->format('Y'));
} elseif ($month > 3 && $month < 7) {
$newDate->modify('first day of april ' . $newDate->format('Y'));
} elseif ($month > 6 && $month < 10) {
$newDate->modify('first day of july ' . $newDate->format('Y'));
} elseif ($month > 9) {
$newDate->modify('first day of october ' . $newDate->format('Y'));
}
break;
case 'month':
$newDate->modify('first day of this month');
break;
case 'week':
$newDate->modify(($newDate->format('w') === '0') ? 'monday last week' : 'monday this week');
break;
}
return $newDate;
}

in PHP 5.3.10 this works
$myDate = new \DateTime(date("Y")."-01-01");
echo $myDate->format("Y-m-d");
In PHP 5.4 and upper you can put all together
echo (new \DateTime(date("Y")."-01-01"))->format("Y-m-d")

As a commenter #Glavić said already
$year = new DateTime('first day of January');
is the solution.
To me it did make sense semantically that "this year" should return midnight of the first day of the year, but indeed it does not!

Following is the code snippet for getting first and last day of the year.
$firstDayOfYear = date('Y-01-01');
$lastDayOfYear = date('Y-12-t');

Try this:
$dt = date('m/d/Y',time());
echo 'First day : '. date("01/01/Y", strtotime($dt)).' - Last day : '. date("m/t/Y", strtotime($dt));

Getting first and last day of the current year using DateTime object.
$currentDate = new \DateTime("NOW");
$yearStartString = $currentDate->format("Y")."-01-01 00:00:00";
$yearEndString = $currentDate->format("Y")."-12-31 23:59:59";
$yearStartDate = \DateTime::createFromFormat("Y-m-d H:i:s", $yearStartString);
$yearEndDate = \DateTime::createFromFormat("Y-m-d H:i:s", $yearEndString);

Related

Get the last day of the current year as date

How can I get the last day (Dec 31) of the current year as a date using PHP?
I tried the following but this doesn't work:
$year = date('Y');
$yearEnd = strtotime($year . '-12-31');
What I need is a date that looks like 2014-12-31 for the current year.
PHP strtotime() uses the current date/time as a basis (so it will use this current year), and you need date() to format:
$yearEnd = date('Y-m-d', strtotime('Dec 31'));
//or
$yearEnd = date('Y-m-d', strtotime('12/31'));
You can just concatenate actual year with required date
$year = date('Y') . '-12-31';
echo $year;
//output 2014-12-31
DateTime is perfectly capable of doing this:
$endOfYear = new \DateTime('last day of December this year');
You can even combine it with more modifiers to get the end of next year:
$endOfNextYear = new \DateTime('last day of December this year +1 years');
Another way to do this is use the Relative Formats of strtotime()
$yearEnd = date('Y-m-d', strtotime('last day of december this year'));
// or
$yearEnd = date('Y-m-d', strtotime('last day of december'));

Getting first / last date of the week

Is it possible to get the first / last date of a week using PHP's Relative Date Time format?
I've tried to do:
date_default_timezone_set('Europe/Amsterdam');
$date = new DateTime();
$date->modify('first day of this week'); // to get the current week's first date
echo $date->format('Y-m-d'); // outputs 2011-12-19
$date->modify('first day of week 50'); // to get the first date of any week by weeknumber
echo $date->format('Y-m-d'); // outputs 2011-12-18
$date->modify('last day of this week'); // to get the current week's last date
echo $date->format('Y-m-d'); // outputs 2011-12-17
$date->modify('last day of week 50'); // to get the last date of any week by weeknumber
echo $date->format('Y-m-d'); // outputs 2011-12-18
As you can see it doesn't output the correct dates.
According to the docs this should be possible if I'm correct.
Am I doing something terrible wrong?
EDIT
I need to use PHP's DateTime for dates in the far future.
UPDATE
It gets only stranger now. I've done some more testing.
Windows PHP 5.3.3
2011-12-01
Warning: DateTime::modify() [datetime.modify]: Failed to parse time string (first day of week 50) at position 13 (w): The timezone could not be found in the database in C:\Users\Gerrie\Desktop\ph\Websites\Charts\www.charts.com\public\index.php on line 9
2011-12-01
2011-11-30
Warning: DateTime::modify() [datetime.modify]: Failed to parse time string (last day of week 50) at position 12 (w): The timezone could not be found in the database in C:\Users\Gerrie\Desktop\ph\Websites\Charts\www.charts.com\public\index.php on line 15
2011-11-30
Linux 5.3.8
2011-12-01
2011-12-01
2011-11-30
2011-11-30
I'm a big fan of using the Carbon library, which makes this sort of thing really easy. For example:
use Carbon\Carbon;
$monday = Carbon::now()->startOfWeek()
$sunday = Carbon::now()->endOfWeek()
Or, if you'd prefer to have Sunday be the first day of your week:
use Carbon\Carbon;
Carbon::setWeekStartsAt(Carbon::SUNDAY);
Carbon::setWeekEndsAt(Carbon::SATURDAY);
$sunday = Carbon::now()->startOfWeek()
$saturday = Carbon::now()->endOfWeek()
According to docs the format strings "first day of" and "last day of" are only allowed for months, not for weeks. See http://www.php.net/manual/en/datetime.formats.relative.php
If you combine first and last day of with a week statement the result either blows the parser or is something that you did not expect (usually the first or last day of a month, not a week).
The difference that you see between Win and Linux is probably only because of different error reporting settings.
To get the first and last day of the current week use:
$date->modify('this week');
$date->modify('this week +6 days');
To get the first and last day of week 50 use:
$date->setISODate(2011, 50);
$date->setISODate(2011, 50, 7);
EDIT:
If you want to use the modify method for absolute week numbers you have to use the formats defined in http://www.php.net/manual/en/datetime.formats.compound.php:
$date->modify('2011W50');
$date->modify('2011W50 +6 days');
if first day of week is Monday
$date->modify('Monday this week');
else if first day is Sunday
$date->modify('Sunday this week');
because in different countries first day of week maybe Monday or Sunday
This is what I am using to get the first and last day of the week from any date.
In this case, monday is the first day of the week...
$date = date('Y-m-d'); // you can put any date you want
$nbDay = date('N', strtotime($date));
$monday = new DateTime($date);
$sunday = new DateTime($date);
$monday->modify('-'.($nbDay-1).' days');
$sunday->modify('+'.(7-$nbDay).' days');
function getweek_first_last_date($date)
{
$cur_date = strtotime($date); // Change to whatever date you need
// Get the day of the week: Sunday = 0 to Saturday = 6
$dotw = date('w', $cur_date);
if($dotw>1)
{
$pre_monday = $cur_date-(($dotw-1)*24*60*60);
$next_sunday = $cur_date+((7-$dotw)*24*60*60);
}
else if($dotw==1)
{
$pre_monday = $cur_date;
$next_sunday = $cur_date+((7-$dotw)*24*60*60);
}
else if($dotw==0)
{
$pre_monday =$cur_date -(6*24*60*60);;
$next_sunday = $cur_date;
}
$date_array = array();
$date_array['start_date_of_week'] = $pre_monday;
$date_array['end_date_of_week'] = $next_sunday;
return $date_array;
}
$date = '2013-12-22';
getweek_first_last_date($date);
Output :
$array_of_week = Array
(
[start_date_of_week] => 1387152000
[end_date_of_week] => 1387670400
)
$start_date =date('d/m/Y', $array_of_week['start_date_of_week'])
<code>
function getlastweek_first_last_date()
{
$cur_date = strtotime(date('Y-m-d')); // Change to whatever date you need
// Get the day of the week: Sunday = 0 to Saturday = 6
$previousweekcurdate = $cur_date - (7*24*3600);
$cur_date = $previousweekcurdate;
$dotw = date('w', $cur_date);
if($dotw>1)
{
$pre_sunday = $cur_date-(($dotw-1)*24*60*60) - (24*60*60);
$next_satday = $cur_date+((7-$dotw)*24*60*60)- (24*60*60);
}
else if($dotw==1)
{
$pre_sunday = $cur_date- (24*60*60);
$next_satday = $cur_date+((7-$dotw)*24*60*60)- (24*60*60);
}
else if($dotw==0)
{
$pre_sunday =$cur_date -(6*24*60*60)- (24*60*60);
$next_satday = $cur_date- (24*60*60);
}
$pre_sunday = date('Y-m-d',$pre_sunday)." 00:00:00";
$next_satday = date('Y-m-d',$next_satday)." 23:59:59";
$date_array = array();
$date_array['sdoflw'] = $pre_sunday;
$date_array['edoflw'] = $next_satday;
return $date_array;
}
$date_array = getlastweek_first_last_date();
echo $start_date_of_week = $date_array['sdoflw'];
echo $end_date_of_week = $date_array['edoflw'];
</code>
Simply you can get the date as follows
first day of week is Monday
date('Y-m-d',strtotime('Monday this week'));
if first day is Sunday
date('Y-m-d',strtotime('Sunday this week'));

PHP DateTime::modify adding and subtracting months

I've been working a lot with the DateTime class and recently ran into what I thought was a bug when adding months. After a bit of research, it appears that it wasn't a bug, but instead working as intended. According to the documentation found here:
Example #2 Beware when adding or
subtracting months
<?php
$date = new DateTime('2000-12-31');
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
?>
The above example will output:
2001-01-31
2001-03-03
Can anyone justify why this isn't considered a bug?
Furthermore does anyone have any elegant solutions to correct the issue and make it so +1 month will work as expected instead of as intended?
Why it's not a bug:
The current behavior is correct. The following happens internally:
+1 month increases the month number (originally 1) by one. This makes the date 2010-02-31.
The second month (February) only has 28 days in 2010, so PHP auto-corrects this by just continuing to count days from February 1st. You then end up at March 3rd.
How to get what you want:
To get what you want is by: manually checking the next month. Then add the number of days next month has.
I hope you can yourself code this. I am just giving what-to-do.
PHP 5.3 way:
To obtain the correct behavior, you can use one of the PHP 5.3's new functionality that introduces the relative time stanza first day of. This stanza can be used in combination with next month, fifth month or +8 months to go to the first day of the specified month. Instead of +1 month from what you're doing, you can use this code to get the first day of next month like this:
<?php
$d = new DateTime( '2010-01-31' );
$d->modify( 'first day of next month' );
echo $d->format( 'F' ), "\n";
?>
This script will correctly output February. The following things happen when PHP processes this first day of next month stanza:
next month increases the month number (originally 1) by one. This makes the date 2010-02-31.
first day of sets the day number to 1, resulting in the date 2010-02-01.
Here is another compact solution entirely using DateTime methods, modifying the object in-place without creating clones.
$dt = new DateTime('2012-01-31');
echo $dt->format('Y-m-d'), PHP_EOL;
$day = $dt->format('j');
$dt->modify('first day of +1 month');
$dt->modify('+' . (min($day, $dt->format('t')) - 1) . ' days');
echo $dt->format('Y-m-d'), PHP_EOL;
It outputs:
2012-01-31
2012-02-29
This may be useful:
echo Date("Y-m-d", strtotime("2013-01-01 +1 Month -1 Day"));
// 2013-01-31
echo Date("Y-m-d", strtotime("2013-02-01 +1 Month -1 Day"));
// 2013-02-28
echo Date("Y-m-d", strtotime("2013-03-01 +1 Month -1 Day"));
// 2013-03-31
echo Date("Y-m-d", strtotime("2013-04-01 +1 Month -1 Day"));
// 2013-04-30
echo Date("Y-m-d", strtotime("2013-05-01 +1 Month -1 Day"));
// 2013-05-31
echo Date("Y-m-d", strtotime("2013-06-01 +1 Month -1 Day"));
// 2013-06-30
echo Date("Y-m-d", strtotime("2013-07-01 +1 Month -1 Day"));
// 2013-07-31
echo Date("Y-m-d", strtotime("2013-08-01 +1 Month -1 Day"));
// 2013-08-31
echo Date("Y-m-d", strtotime("2013-09-01 +1 Month -1 Day"));
// 2013-09-30
echo Date("Y-m-d", strtotime("2013-10-01 +1 Month -1 Day"));
// 2013-10-31
echo Date("Y-m-d", strtotime("2013-11-01 +1 Month -1 Day"));
// 2013-11-30
echo Date("Y-m-d", strtotime("2013-12-01 +1 Month -1 Day"));
// 2013-12-31
My solution to the problem:
$startDate = new \DateTime( '2015-08-30' );
$endDate = clone $startDate;
$billing_count = '6';
$billing_unit = 'm';
$endDate->add( new \DateInterval( 'P' . $billing_count . strtoupper( $billing_unit ) ) );
if ( intval( $endDate->format( 'n' ) ) > ( intval( $startDate->format( 'n' ) ) + intval( $billing_count ) ) % 12 )
{
if ( intval( $startDate->format( 'n' ) ) + intval( $billing_count ) != 12 )
{
$endDate->modify( 'last day of -1 month' );
}
}
I agree with the sentiment of the OP that this is counter-intuitive and frustrating, but so is determining what +1 month means in the scenarios where this occurs. Consider these examples:
You start with 2015-01-31 and want to add a month 6 times to get a scheduling cycle for sending an email newsletter. With the OP's initial expectations in mind, this would return:
2015-01-31
2015-02-28
2015-03-31
2015-04-30
2015-05-31
2015-06-30
Right away, notice that we are expecting +1 month to mean last day of month or, alternatively, to add 1 month per iteration but always in reference to the start point. Instead of interpreting this as "last day of month" we could read it as "31st day of next month or last available within that month". This means that we jump from April 30th to May 31st instead of to May 30th. Note that this is not because it is "last day of month" but because we want "closest available to date of start month."
So suppose one of our users subscribes to another newsletter to start on 2015-01-30. What is the intuitive date for +1 month? One interpretation would be "30th day of next month or closest available" which would return:
2015-01-30
2015-02-28
2015-03-30
2015-04-30
2015-05-30
2015-06-30
This would be fine except when our user gets both newsletters on the same day. Let's assume that this is a supply-side issue instead of demand-side We're not worried that the user will be annoyed with getting 2 newsletters in the same day but instead that our mail servers can't afford the bandwidth for sending twice as many newsletters. With that in mind, we return to the other interpretation of "+1 month" as "send on the second to last day of each month" which would return:
2015-01-30
2015-02-27
2015-03-30
2015-04-29
2015-05-30
2015-06-29
Now we've avoided any overlap with the first set, but we also end up with April and June 29th, which certainly does match our original intuitions that +1 month simply should return m/$d/Y or the attractive and simple m/30/Y for all possible months. So now let's consider a third interpretation of +1 month using both dates:
Jan. 31st
2015-01-31
2015-03-03
2015-03-31
2015-05-01
2015-05-31
2015-07-01
Jan. 30th
2015-01-30
2015-03-02
2015-03-30
2015-04-30
2015-05-30
2015-06-30
The above has some issues. February is skipped, which could be a problem both supply-end (say if there is a monthly bandwidth allocation and Feb goes to waste and March gets doubled up on) and demand-end (users feel cheated out of Feb and perceive the extra March as attempt to correct mistake). On the other hand, notice that the two date sets:
never overlap
are always on the same date when that month has the date (so the Jan. 30 set looks pretty clean)
are all within 3 days (1 day in most cases) of what might be considered the "correct" date.
are all at least 28 days (a lunar month) from their successor and predecessor, so very evenly distributed.
Given the last two sets, it would not be difficult to simply roll back one of the dates if it falls outside of the actual following month (so roll back to Feb 28th and April 30th in the first set) and not lose any sleep over the occasional overlap and divergence from the "last day of month" vs "second to last day of month" pattern. But expecting the library to choose between "most pretty/natural", "mathematical interpretation of 02/31 and other month overflows", and "relative to first of month or last month" is always going to end with someone's expectations not being met and some schedule needing to adjust the "wrong" date to avoid the real-world problem that the "wrong" interpretation introduces.
So again, while I also would expect +1 month to return a date that actually is in the following month, it is not as simple as intuition and given the choices, going with math over the expectations of web developers is probably the safe choice.
Here's an alternative solution that is still as clunky as any but I think has nice results:
foreach(range(0,5) as $count) {
$new_date = clone $date;
$new_date->modify("+$count month");
$expected_month = $count + 1;
$actual_month = $new_date->format("m");
if($expected_month != $actual_month) {
$new_date = clone $date;
$new_date->modify("+". ($count - 1) . " month");
$new_date->modify("+4 weeks");
}
echo "* " . nl2br($new_date->format("Y-m-d") . PHP_EOL);
}
It's not optimal but the underlying logic is : If adding 1 month results in a date other than the expected next month, scrap that date and add 4 weeks instead. Here are the results with the two test dates:
Jan. 31st
2015-01-31
2015-02-28
2015-03-31
2015-04-28
2015-05-31
2015-06-28
Jan. 30th
2015-01-30
2015-02-27
2015-03-30
2015-04-30
2015-05-30
2015-06-30
(My code is a mess and wouldn't work in a multi-year scenario. I welcome anyone to rewrite the solution with more elegant code so long as the underlying premise is kept intact, i.e. if +1 month returns a funky date, use +4 weeks instead.)
In conjunction with shamittomar's answer, it could then be this for adding months "safely":
/**
* Adds months without jumping over last days of months
*
* #param \DateTime $date
* #param int $monthsToAdd
* #return \DateTime
*/
public function addMonths($date, $monthsToAdd) {
$tmpDate = clone $date;
$tmpDate->modify('first day of +'.(int) $monthsToAdd.' month');
if($date->format('j') > $tmpDate->format('t')) {
$daysToAdd = $tmpDate->format('t') - 1;
}else{
$daysToAdd = $date->format('j') - 1;
}
$tmpDate->modify('+ '. $daysToAdd .' days');
return $tmpDate;
}
I made a function that returns a DateInterval to make sure that adding a month shows the next month, and removes the days into the after that.
$time = new DateTime('2014-01-31');
echo $time->format('d-m-Y H:i') . '<br/>';
$time->add( add_months(1, $time));
echo $time->format('d-m-Y H:i') . '<br/>';
function add_months( $months, \DateTime $object ) {
$next = new DateTime($object->format('d-m-Y H:i:s'));
$next->modify('last day of +'.$months.' month');
if( $object->format('d') > $next->format('d') ) {
return $object->diff($next);
} else {
return new DateInterval('P'.$months.'M');
}
}
This is an improved version of Kasihasi's answer in a related question. This will correctly add or subtract an arbitrary number of months to a date.
public static function addMonths($monthToAdd, $date) {
$d1 = new DateTime($date);
$year = $d1->format('Y');
$month = $d1->format('n');
$day = $d1->format('d');
if ($monthToAdd > 0) {
$year += floor($monthToAdd/12);
} else {
$year += ceil($monthToAdd/12);
}
$monthToAdd = $monthToAdd%12;
$month += $monthToAdd;
if($month > 12) {
$year ++;
$month -= 12;
} elseif ($month < 1 ) {
$year --;
$month += 12;
}
if(!checkdate($month, $day, $year)) {
$d2 = DateTime::createFromFormat('Y-n-j', $year.'-'.$month.'-1');
$d2->modify('last day of');
}else {
$d2 = DateTime::createFromFormat('Y-n-d', $year.'-'.$month.'-'.$day);
}
return $d2->format('Y-m-d');
}
For example:
addMonths(-25, '2017-03-31')
will output:
'2015-02-28'
I found a shorter way around it using the following code:
$datetime = new DateTime("2014-01-31");
$month = $datetime->format('n'); //without zeroes
$day = $datetime->format('j'); //without zeroes
if($day == 31){
$datetime->modify('last day of next month');
}else if($day == 29 || $day == 30){
if($month == 1){
$datetime->modify('last day of next month');
}else{
$datetime->modify('+1 month');
}
}else{
$datetime->modify('+1 month');
}
echo $datetime->format('Y-m-d H:i:s');
Here is an implementation of an improved version of Juhana's answer in a related question:
<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
$addMon = clone $currentDate;
$addMon->add(new DateInterval("P1M"));
$nextMon = clone $currentDate;
$nextMon->modify("last day of next month");
if ($addMon->format("n") == $nextMon->format("n")) {
$recurDay = $createdDate->format("j");
$daysInMon = $addMon->format("t");
$currentDay = $currentDate->format("j");
if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
$addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
}
return $addMon;
} else {
return $nextMon;
}
}
This version takes $createdDate under the presumption that you are dealing with a recurring monthly period, such as a subscription, that started on a specific date, such as the 31st. It always takes $createdDate so late "recurs on" dates won't shift to lower values as they are pushed forward thru lesser-valued months (e.g., so all 29th, 30th or 31st recur dates won't eventually get stuck on the 28th after passing thru a non-leap-year February).
Here is some driver code to test the algorithm:
$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;
$next = sameDateNextMonth($createdDate, $createdDate);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
foreach(range(1, 12) as $i) {
$next = sameDateNextMonth($createdDate, $next);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
}
Which outputs:
created date = 2015-03-31
next date = 2015-04-30
next date = 2015-05-31
next date = 2015-06-30
next date = 2015-07-31
next date = 2015-08-31
next date = 2015-09-30
next date = 2015-10-31
next date = 2015-11-30
next date = 2015-12-31
next date = 2016-01-31
next date = 2016-02-29
next date = 2016-03-31
next date = 2016-04-30
$ds = new DateTime();
$ds->modify('+1 month');
$ds->modify('first day of this month');
If you just want to avoid skipping a month you can perform something like this to get the date out and run a loop on the next month reducing the date by one and rechecking until a valid date where $starting_calculated is a valid string for strtotime (i.e. mysql datetime or "now"). This finds the very end of the month at 1 minute to midnight instead of skipping the month.
$start_dt = $starting_calculated;
$next_month = date("m",strtotime("+1 month",strtotime($start_dt)));
$next_month_year = date("Y",strtotime("+1 month",strtotime($start_dt)));
$date_of_month = date("d",$starting_calculated);
if($date_of_month>28){
$check_date = false;
while(!$check_date){
$check_date = checkdate($next_month,$date_of_month,$next_month_year);
$date_of_month--;
}
$date_of_month++;
$next_d = $date_of_month;
}else{
$next_d = "d";
}
$end_dt = date("Y-m-$next_d 23:59:59",strtotime("+1 month"));
Extension for DateTime class which solves problem of adding or subtracting months
https://gist.github.com/66Ton99/60571ee49bf1906aaa1c
If using strtotime() just use $date = strtotime('first day of +1 month');
I needed to get a date for 'this month last year' and it becomes unpleasant quite quickly when this month is February in a leap year. However, I believe this works... :-/ The trick seems to be to base your change on the 1st day of the month.
$this_month_last_year_end = new \DateTime();
$this_month_last_year_end->modify('first day of this month');
$this_month_last_year_end->modify('-1 year');
$this_month_last_year_end->modify('last day of this month');
$this_month_last_year_end->setTime(23, 59, 59);
$month = 1; $year = 2017;
echo date('n', mktime(0, 0, 0, $month + 2, -1, $year));
will output 2 (february). will work for other months too.
$current_date = new DateTime('now');
$after_3_months = $current_date->add(\DateInterval::createFromDateString('+3 months'));
For days:
$after_3_days = $current_date->add(\DateInterval::createFromDateString('+3 days'));
Important:
The method add() of DateTime class modify the object value so after calling add() on a DateTime Object it returns the new date object and also it modify the object it self.
you can actually do it with just date() and strtotime() as well. For example to add 1 month to todays date:
date("Y-m-d",strtotime("+1 month",time()));
if you are wanting to use the datetime class thats fine too but this is just as easy. more details here
$date = date('Y-m-d', strtotime("+1 month"));
echo $date;

increment date by one month

Let's say I have a date in the following format: 2010-12-11 (year-mon-day)
With PHP, I want to increment the date by one month, and I want the year to be automatically incremented, if necessary (i.e. incrementing from December 2012 to January 2013).
Regards.
$time = strtotime("2010.12.11");
$final = date("Y-m-d", strtotime("+1 month", $time));
// Finally you will have the date you're looking for.
I needed similar functionality, except for a monthly cycle (plus months, minus 1 day). After searching S.O. for a while, I was able to craft this plug-n-play solution:
function add_months($months, DateTime $dateObject)
{
$next = new DateTime($dateObject->format('Y-m-d'));
$next->modify('last day of +'.$months.' month');
if($dateObject->format('d') > $next->format('d')) {
return $dateObject->diff($next);
} else {
return new DateInterval('P'.$months.'M');
}
}
function endCycle($d1, $months)
{
$date = new DateTime($d1);
// call second function to add the months
$newDate = $date->add(add_months($months, $date));
// goes back 1 day from date, remove if you want same day of month
$newDate->sub(new DateInterval('P1D'));
//formats final date to Y-m-d form
$dateReturned = $newDate->format('Y-m-d');
return $dateReturned;
}
Example:
$startDate = '2014-06-03'; // select date in Y-m-d format
$nMonths = 1; // choose how many months you want to move ahead
$final = endCycle($startDate, $nMonths); // output: 2014-07-02
Use DateTime::add.
$start = new DateTime("2010-12-11", new DateTimeZone("UTC"));
$month_later = clone $start;
$month_later->add(new DateInterval("P1M"));
I used clone because add modifies the original object, which might not be desired.
strtotime( "+1 month", strtotime( $time ) );
this returns a timestamp that can be used with the date function
You can use DateTime::modify like this :
$date = new DateTime('2010-12-11');
$date->modify('+1 month');
See documentations :
https://php.net/manual/en/datetime.modify.php
https://php.net/manual/en/class.datetime.php
UPDATE january 2021 : correct mistakes raised by comments
This solution has some problems for months with 31 days like May etc.
Exemple : this jumps from 31st May to 1st July which is incorrect.
To correct that, you can create this custom function
function addMonths($date,$months){
$init=clone $date;
$modifier=$months.' months';
$back_modifier =-$months.' months';
$date->modify($modifier);
$back_to_init= clone $date;
$back_to_init->modify($back_modifier);
while($init->format('m')!=$back_to_init->format('m')){
$date->modify('-1 day') ;
$back_to_init= clone $date;
$back_to_init->modify($back_modifier);
}
}
Then you can use it like that :
$date = new DateTime('2010-05-31');
addMonths($date, 1);
print_r($date);
//DateTime Object ( [date] => 2010-06-30 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Berlin )
This solution was found in PHP.net posted by jenspj : https://www.php.net/manual/fr/datetime.modify.php#107592
(date('d') > 28) ? date("mdY", strtotime("last day of next month")) : date("mdY", strtotime("+1 month"));
This will compensate for February and the other 31 day months. You could of course do a lot more checking to to get more exact for 'this day next month' relative date formats (which does not work sadly, see below), and you could just as well use DateTime.
Both DateInterval('P1M') and strtotime("+1 month") are essentially blindly adding 31 days regardless of the number of days in the following month.
2010-01-31 => March 3rd
2012-01-31 => March 2nd (leap year)
Please first you set your date format as like 12-12-2012
After use this function it's work properly;
$date = date('d-m-Y',strtotime("12-12-2012 +2 Months");
Here 12-12-2012 is your date and +2 Months is increment of the month;
You also increment of Year, Date
strtotime("12-12-2012 +1 Year");
Ans is 12-12-2013
I use this way:-
$occDate='2014-01-28';
$forOdNextMonth= date('m', strtotime("+1 month", strtotime($occDate)));
//Output:- $forOdNextMonth=02
/*****************more example****************/
$occDate='2014-12-28';
$forOdNextMonth= date('m', strtotime("+1 month", strtotime($occDate)));
//Output:- $forOdNextMonth=01
//***********************wrong way**********************************//
$forOdNextMonth= date('m', strtotime("+1 month", $occDate));
//Output:- $forOdNextMonth=02; //instead of $forOdNextMonth=01;
//******************************************************************//
Just updating the answer with simple method for find the date after no of months. As the best answer marked doesn't give the correct solution.
<?php
$date = date('2020-05-31');
$current = date("m",strtotime($date));
$next = date("m",strtotime($date."+1 month"));
if($current==$next-1){
$needed = date('Y-m-d',strtotime($date." +1 month"));
}else{
$needed = date('Y-m-d', strtotime("last day of next month",strtotime($date)));
}
echo "Date after 1 month from 2020-05-31 would be : $needed";
?>
If you want to get the date of one month from now you can do it like this
echo date('Y-m-d', strtotime('1 month'));
If you want to get the date of two months from now, you can achieve that by doing this
echo date('Y-m-d', strtotime('2 month'));
And so on, that's all.
Thanks Jason, your post was very helpful. I reformatted it and added more comments to help me understand it all. In case that helps anyone, I have posted it here:
function cycle_end_date($cycle_start_date, $months) {
$cycle_start_date_object = new DateTime($cycle_start_date);
//Find the date interval that we will need to add to the start date
$date_interval = find_date_interval($months, $cycle_start_date_object);
//Add this date interval to the current date (the DateTime class handles remaining complexity like year-ends)
$cycle_end_date_object = $cycle_start_date_object->add($date_interval);
//Subtract (sub) 1 day from date
$cycle_end_date_object->sub(new DateInterval('P1D'));
//Format final date to Y-m-d
$cycle_end_date = $cycle_end_date_object->format('Y-m-d');
return $cycle_end_date;
}
//Find the date interval we need to add to start date to get end date
function find_date_interval($n_months, DateTime $cycle_start_date_object) {
//Create new datetime object identical to inputted one
$date_of_last_day_next_month = new DateTime($cycle_start_date_object->format('Y-m-d'));
//And modify it so it is the date of the last day of the next month
$date_of_last_day_next_month->modify('last day of +'.$n_months.' month');
//If the day of inputted date (e.g. 31) is greater than last day of next month (e.g. 28)
if($cycle_start_date_object->format('d') > $date_of_last_day_next_month->format('d')) {
//Return a DateInterval object equal to the number of days difference
return $cycle_start_date_object->diff($date_of_last_day_next_month);
//Otherwise the date is easy and we can just add a month to it
} else {
//Return a DateInterval object equal to a period (P) of 1 month (M)
return new DateInterval('P'.$n_months.'M');
}
}
$cycle_start_date = '2014-01-31'; // select date in Y-m-d format
$n_months = 1; // choose how many months you want to move ahead
$cycle_end_date = cycle_end_date($cycle_start_date, $n_months); // output: 2014-07-02
function dayOfWeek($date){
return DateTime::createFromFormat('Y-m-d', $date)->format('N');
}
Usage examples:
echo dayOfWeek(2016-12-22);
// "4"
echo dayOfWeek(date('Y-m-d'));
// "4"
$date = strtotime("2017-12-11");
$newDate = date("Y-m-d", strtotime("+1 month", $date));
If you want to increment by days you can also do it
$date = strtotime("2017-12-11");
$newDate = date("Y-m-d", strtotime("+5 day", $date));
For anyone looking for an answer to any date format.
echo date_create_from_format('d/m/Y', '15/04/2017')->add(new DateInterval('P1M'))->format('d/m/Y');
Just change the date format.
//ECHO MONTHS BETWEEN TWO TIMESTAMPS
$my_earliest_timestamp = 1532095200;
$my_latest_timestamp = 1554991200;
echo '<pre>';
echo "Earliest timestamp: ". date('c',$my_earliest_timestamp) ."\r\n";
echo "Latest timestamp: " .date('c',$my_latest_timestamp) ."\r\n\r\n";
echo "Month start of earliest timestamp: ". date('c',strtotime('first day of '. date('F Y',$my_earliest_timestamp))) ."\r\n";
echo "Month start of latest timestamp: " .date('c',strtotime('first day of '. date('F Y',$my_latest_timestamp))) ."\r\n\r\n";
echo "Month end of earliest timestamp: ". date('c',strtotime('last day of '. date('F Y',$my_earliest_timestamp)) + 86399) ."\r\n";
echo "Month end of latest timestamp: " .date('c',strtotime('last day of '. date('F Y',$my_latest_timestamp)) + 86399) ."\r\n\r\n";
$sMonth = strtotime('first day of '. date('F Y',$my_earliest_timestamp));
$eMonth = strtotime('last day of '. date('F Y',$my_earliest_timestamp)) + 86399;
$xMonth = strtotime('+1 month', strtotime('first day of '. date('F Y',$my_latest_timestamp)));
while ($eMonth < $xMonth) {
echo "Things from ". date('Y-m-d',$sMonth) ." to ". date('Y-m-d',$eMonth) ."\r\n\r\n";
$sMonth = $eMonth + 1; //add 1 second to bring forward last date into first second of next month.
$eMonth = strtotime('last day of '. date('F Y',$sMonth)) + 86399;
}
I find the mtkime() function works really well for this:
$start_date="2021-10-01";
$start_date_plus_a_month=date("Y-m-d", mktime(0, 0, 0, date("m",strtotime($start_date))+1, date("d",strtotime($start_date)), date("Y",strtotime($start_date))));
result: 2021-11-01
I like to subtract 1 from the 'day' to produce '2021-10-31' which can be useful if you want to display a range across 12 months, e.g. Oct 1, 2021 to Sep 30 2022
$start_date_plus_a_year=date("Y-m-d", mktime(0, 0, 0, date("m",strtotime($start_date))+12, date("d",strtotime($start_date))-1, date("Y",strtotime($start_date))));
result: 2022-09-30
The correct answer to the exact question asked is Giuseppe Canale's answer from earlier. I'm going to answer a slightly more generic question of how to increment the date by an arbitrary number of months, however.
<?php
/**
* Will return a timestamp corresponding to first day of the month that is N months into the future.
* #param int $months_later number of months into the future: 0 for current one
* #param string $today if supplied will be used as the "now" time
* #return int
*/
function rel_month_to_time($months_later, $today=null) {
if ($months_later===0) {
return is_null($today) ? time() : strtotime($today);
}
return strtotime('first day of next month', rel_month_to_time($months_later-1, $today));
}
As is many times the case, you can use recursion for these "human problems" like calendars. The above can be used to return a timestamp corresponding to "next month" -- the way we humans think of it.
<?php echo date('Y-m-d', rel_month_to_time(1, '2023-01-30'));
// 2023-02-01
As pointed by #NetVicious i corrected the code, it should work with all dates, some example:
2013-01-30 will be 2013-02-28
2013-05-15 will be 2013-05-15
2013-05-31 will be 2013-06-30
This code uses the DateTime class to create a new date object, then it adds 1 month to the date using the modify method. Next, it gets the day of the next month using the format method. If the next month's day doesn't match the original day, it modifies the date to the last day of the previous month using the modify method.
$original_date = "2013-01-30";
$original_day = date("d", strtotime($original_date));
$date = new DateTime($original_date);
$date->modify('+1 month');
$next_month_day = $date->format('d');
if ($next_month_day != $original_day) {
$date->modify('last day of previous month');
}
$new_date = $date->format('Y-m-d');
echo $new_date;
All presented solutions are not working properly.
strtotime() and DateTime::add or DateTime::modify give sometime invalid results.
Examples:
- 31.08.2019 + 1 month gives 01.10.2019 instead 30.09.2019
- 29.02.2020 + 1 year gives 01.03.2021 instead 28.02.2021
(tested on PHP 5.5, PHP 7.3)
Below is my function based on idea posted by Angelo that solves the problem:
// $time - unix time or date in any format accepted by strtotime() e.g. 2020-02-29
// $days, $months, $years - values to add
// returns new date in format 2021-02-28
function addTime($time, $days, $months, $years)
{
// Convert unix time to date format
if (is_numeric($time))
$time = date('Y-m-d', $time);
try
{
$date_time = new DateTime($time);
}
catch (Exception $e)
{
echo $e->getMessage();
exit;
}
if ($days)
$date_time->add(new DateInterval('P'.$days.'D'));
// Preserve day number
if ($months or $years)
$old_day = $date_time->format('d');
if ($months)
$date_time->add(new DateInterval('P'.$months.'M'));
if ($years)
$date_time->add(new DateInterval('P'.$years.'Y'));
// Patch for adding months or years
if ($months or $years)
{
$new_day = $date_time->format("d");
// The day is changed - set the last day of the previous month
if ($old_day != $new_day)
$date_time->sub(new DateInterval('P'.$new_day.'D'));
}
// You can chage returned format here
return $date_time->format('Y-m-d');
}
Usage examples:
echo addTime('2020-02-29', 0, 0, 1); // add 1 year (result: 2021-02-28)
echo addTime('2019-08-31', 0, 1, 0); // add 1 month (result: 2019-09-30)
echo addTime('2019-03-15', 12, 2, 1); // add 12 days, 2 months, 1 year (result: 2019-09-30)
put a date in input box then click the button get day from date in jquery
$(document).ready( function() {
$("button").click(function(){
var day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
var a = new Date();
$(".result").text(day[a.getDay()]);
});
});
<?php
$selectdata ="select fromd,tod from register where username='$username'";
$q=mysqli_query($conm,$selectdata);
$row=mysqli_fetch_array($q);
$startdate=$row['fromd'];
$stdate=date('Y', strtotime($startdate));
$endate=$row['tod'];
$enddate=date('Y', strtotime($endate));
$years = range ($stdate,$enddate);
echo '<select name="years" class="form-control">';
echo '<option>SELECT</option>';
foreach($years as $year)
{ echo '<option value="'.$year.'"> '.$year.' </option>'; }
echo '</select>'; ?>

How to find first day of the next month and remaining days till this date with PHP

How can I find first day of the next month and the remaining days till this day from the present day?
Thank you
Create a timestamp for 00:00 on the first day of next month:
$firstDayNextMonth = strtotime('first day of next month');
The number of days til that date is the number of seconds between now and then divided by (24 * 60 * 60).
$daysTilNextMonth = ($firstDayNextMonth - time()) / (24 * 3600);
$firstDayNextMonth = date('Y-m-d', strtotime('first day of next month'));
For getting first day after two months from current
$firstDayAfterTwoMonths = date('Y-m-d', strtotime('first day of +2 month'));
You can use DateTime object like this to find out the first day of next month like this:
$date = new DateTime('first day of next month');
You can do this to know how many days left from now to the first day of next month:
$date = new DateTime('now');
$nowTimestamp = $date->getTimestamp();
$date->modify('first day of next month');
$firstDayOfNextMonthTimestamp = $date->getTimestamp();
echo ($firstDayOfNextMonthTimestamp - $nowTimestamp) / 86400;
The easiest and quickest way is to use strtotime() which recognizes 'first day next month';
$firstDayNextMonth = date('Y-m-d', strtotime('first day next month'));
Since I googled this and came to this answer, I figured I'd include a more modern answer that works for PHP 5.3.0+.
//Your starting date as DateTime
$currentDate = new DateTime(date('Y-m-d'));
//Add 1 month
$currentDate->add(new DateInterval('P1M'));
//Get the first day of the next month as string
$firstDayOfNextMonth = $currentDate->format('Y-m-1');
You can get the first of the next month with this:
$now = getdate();
$nextmonth = ($now['mon'] + 1) % 13 + 1;
$year = $now['year'];
if($nextmonth == 1)
$year++;
$thefirst = gmmktime(0, 0, 0, $nextmonth, $year);
With this example, $thefirst will be the UNIX timestamp for the first of the next month. Use date to format it to your liking.
This will give you the remaining days in the month:
$now = getdate();
$months = array(
31,
28 + ($now['year'] % 4 == 0 ? 1 : 0), // Support for leap years!
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
);
$days = $months[$now['mon'] - 1];
$daysleft = $days - $now['mday'];
The number of days left will be stored in $daysleft.
Hope this helps!
$firstDayNextMonth = date('Y-m-d', mktime(0, 0, 0, date('m')+1, 1, date('Y')));
As another poster has mentioned the DateInterval object does not give accurate results for the next month when you use dates such as 1/31/2016 or 8/31/2016 as it skips the next month. My solution was to still use the DateInterval object but reformat your current date to be the first day of the current month prior to utilizing the DateInterval.
$currentDate = '8/31/2016';
$date = new DateTime(date("n", strtotime($currentDate))."/1/".date("Y", strtotime($currentDate)));
//add 1 month
$date->add(new DateInterval('P1M'));
$currentDate=$date->format('m/1/Y');
echo($currentDate);
easiest way to get the last day of the month
date('Y-m-d', mktime(0, 0, 0, date('m')+1, 1, date('Y')));
I took mattbasta's approach because it's able to get the 'first day of next month' with a given date, but there is a tiny problem in calculating the $nextmonth. The fix is as below:
$now = getdate();
$nextmonth = ($now['mon'] + 1) % 13 + 1;
$year = $now['year'];
if($nextmonth == 1)
$year++;
else
$nextmonth--;
$thefirst = gmmktime(0, 0, 0, $nextmonth, $year);
I initially thought about using a DateInterval object (as discussed above in another answer) but it is not reliable. For example, if the current DateTime is 31 January and then we add on a month (to get the next month) then it will skip February completely!
Here is my solution:
function start_of_next_month(DateTime $datetime)
{
$year = (int) $datetime->format('Y');
$month = (int) $datetime->format('n');
$month += 1;
if ($month === 13)
{
$month = 1;
$year += 1;
}
return new DateTime($year . '-' . $month . '-01');
}
Even easier way to get first and last day of next month
$first = strttotime("first day of next month");
$last = strttotime("last day of next month");
You could do something like this. To have this functionality, you need to make use of a php library available in https://packagist.org/packages/ishworkh/navigable-date.
With that is really easy to do what you're asking for here.
For e.g:
$format = 'Y-m-d H:i:s';
$Date = \NavigableDate\NavigableDateFacade::create('2017-02-24');
var_dump($Date->format($format));
$resetTime = true;
$resetDays = true;
$NextMonth = $Date->nextMonth($resetTime, $resetDays);
var_dump($NextMonth->format($format));
$DayUntilFirstOfNextMonth = $NextMonth->getDifference($Date);
var_dump('Days left:' . $DayUntilFirstOfNextMonth->format('%d'));
gives you ouput:
string(19) "2017-02-24 00:00:00"
string(19) "2017-03-01 00:00:00"
string(11) "Days left:5"
Note: Additionally this library let you navigate through dates by day(s), week(s), year(s) forward or backward. For more information look into its README.
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
To get the first day of next month a clean solution:
<?php
$date = new DateTimeInmutable('now');
$date->modify('first day of next month');//here the magic occurs
echo $date->format('Y-m-d') . '\n';
Since you just want to calculate it I suggest using DateTimeInmutable class.
using the class DateTime and $date->modify('first day of next month'); will modify your original date value.
$month = date('m')+1;
if ($month<10) {
$month = '0'.$month;
}
echo date('Y-').$month.'-01';
Simplest way to achieve this. You can echo or store into variable.
I came up with this for my needs:
if(date('m') == 12) { $next_month = 1; } else { $next_month = date('m')+1; }
if($next_month == 1) { $year_start = date('Y')+1; } else { $year_start = date('Y'); }
$date_start_of_next_month = $year_start . '-' . $next_month . '-01 00:00:00';
if($next_month == 12) { $month_after = 1; } else { $month_after = $next_month+1; }
if($month_after == 1) { $year_end = date('Y')+1; } else { $year_end = date('Y'); }
$date_start_of_month_after_next = $year_end . '-' . $month_after . '-01 00:00:00';
Please note that instead of getting $date_end_of_next_month I chose to go with a $date_start_of_month_after_next date, it avoids the hassles with leap years and months containing different number of days.
You can simply use the >= comparaision sign for $date_start_of_next_month and the < one for $date_start_of_month_after_next.
If you prefer a timestamp format for the date, from there you will want to apply the strtotime() native function of PHP on these two variables.
You can use the php date method to find the current month and date, and then you would need to have a short list to find how many days in that month and subtract (leap year would require extra work).

Categories