Carbon('last day of October')->modify('+1 month') unexpected result - php

Can anyone explain to me, why (new Carbon('last day of October'))->modify('+1 month'); returns
Carbon {#326
+"date": "2016-12-01 00:00:00.000000"
+"timezone_type": 3
+"timezone": "Europe/"
}
Same with modify('-1 month'). Could that be that when modifying by a month, Carbon substracts or adds a number of days in the target month? So, when we add "1 month" to the last day of October, Carbon adds 31 days to October 31 and return December 1st...

Seems Carbon library still has some bugs.
You can try this way.
Carbon::create()->endOfMonth()->month(10)->modify('+1 month')
You can check the result at http://phpio.net/tools/carbon

The last day of October evaluates to Oct 31st of the current year.
Oct 31st +1 month is Nov 31st. That's an invalid date. But obviously it should be the same as Nov 30th +1 day, which is Dec 1st.
The problem is that both evaluations are done independently. modify("+1 month") doesn't know that it's supposed to result in the "last day" of that month.
You can't get around this issue by using endOfMonth(), except when it's actually the last date change in the chain. It's basically identical to modify("last day of this month") but also advances the time to 1µs before midnight.
Instead you could concatenate the strings into a single expression, eg. last day of October +1 month.

Related

How to add a year to today's date and default it to the preceding working day

If I want to default a date to the next working day I am using the following:
<?php
echo(date('d/m/Y',strtotime('+1 Weekdays')));
?>
For example: If a user is adding an item on a Friday it is given a default of the following Monday - the next working day.
I have to create a schedule of events with a start and end date. The end date needs to 1 year in the future on the preceding working day.
For example: If a user adds a schedule that has a start day of Wednesday and the same date in a years time happens to be a Sunday, then the end date needs to default to the previous Friday - the preceding working day.
I found the answer:
<?php
echo(date(date('d/m/Y',strtotime('+1 year')),strtotime('-1 Weekdays')));
?>
You just need to add one year to today's date then check the day of the week, if it is 'Sat' or 'Sun' subtract one weekday. The PHP DateTime object makes this easy with the format() and modify() methods.
$inOneYear = new DateTime('+1 year');
if(in_array($inOneYear->format('D'), ['Sat', 'Sun'])){
$inOneYear->modify('-1 weekday');
}
echo $inOneYear->format('D, d/m/Y');
In all these cases:
today (Thursday, Dec. 1st, 2022)
tomorrow (Friday, Dec. 2nd, 2022)
the next day (Saturday, Dec. 3rd, 2022)
the above will output:
Fri, 01/12/2023
The strtotime() function and the DateTime constructor both take stacking relative values, and will process them in order, so you can do things like:
$when = strtotime('now +1 year -1 weekdays');
$when = new DateTime('now +1 year -1 weekdays');

How to get the starting weekday of a month in a future year using date() in php

I am using a date() format to return the starting weekday of a month. The code I have below is how I am attempting to achieve this. For the current year (2018) this works as normal. For example This month is august and the starting weekday is a Wednesday so it will return a 3 for Wednesday. (It works so far)
As we advance the year to 2019 it starts to get the starting weekday wrong.
For example January 2019 starts on a Tuesday so it should return 2 but returns 1. (one day out)
This error seems to be cumulative so if we go to 2020 then it is 2 days out etc.
I have tried so hard to format this Date() correctly but to no avail. Is this even the correct way to do this?
Code:
$future_month = 5 /*for January 2019*/
$starting_weekday = date('N',mktime(0, 0, 0, date('m', strtotime('+'.$future_month.' months', strtotime(date('Y-m-01')))), 1));
Many Thanks
Cameron
Your code makes this much more complicated than it needs to be.
$dt = new DateTime('first day of +5 months')
$dt->format('N'); // "2"

PHP strtotime +1 month adding an extra month [duplicate]

This question already has answers here:
PHP: Adding months to a date, while not exceeding the last day of the month
(7 answers)
Closed 9 years ago.
I have a simple variable that adds one month to today:
$endOfCycle = date("Y-m", strtotime("+1 month"));
Today is January 2013, so I would expect to get back 2013-02 but I'm getting 2013-03 instead. I can't figure out why it's jumping to March.
It's jumping to March because today is 29th Jan, and adding a month gives 29th Feb, which doesn't exist, so it's moving to the next valid date.
This will happen on the 31st of a lot of months as well, but is obviously more noticable in the case of January to Feburary because Feb is shorter.
If you're not interested in the day of month and just want it to give the next month, you should specify the input date as the first of the current month. This will always give you the correct answer if you add a month.
For the same reason, if you want to always get the last day of the next month, you should start by calculating the first of the month after the one you want, and subtracting a day.
This should be
$endOfCycle=date('Y-m-d', strtotime("+30 days"));
strtotime
expects to be given a string containing a US English date format and will try to parse that format into a Unix timestamp (the number of seconds since January 1 1970 00:00:00 UTC), relative to the timestamp given in now, or the current time if now is not supplied.
while
date
Returns a string formatted according to the given format string using the given integer timestamp or the current time if no timestamp is given.
See the manual pages for:
http://www.php.net/manual/en/function.strtotime.php
http://www.php.net/manual/en/function.date.php
You can use this code to get the next month:
$ts = mktime(0, 0, 0, date("n") + 1, 1);
echo date("Y-m-d H:i:s", $ts);
echo date("n", $ts);
Assuming today is 2013-01-31 01:23:45 the above will return:
2013-02-01 00:00:00
2
today is 29th of January, +1 month means 29th of Fabruary, but because February consists of 28 days this year, it overlaps to the next day which is March 1st
instead try
strtotime('next month')
Maybe because its 2013-01-29 so +1 month would be 2013-02-29 which doesn't exist so it would be 2013-03-01
You could try
date('m/d/y h:i a',(strtotime('next month',strtotime(date('m/01/y')))));
from the comments on http://php.net/manual/en/function.strtotime.php
$endOfCycle = date("Y-m", mktime(0, 0, 0, date("m", time())+1 , 15, date("m", time())));
try this:
$endOfCycle = date("Y-m", time()+2592000);
this adds 30 days, not exactly a month tough.

php datetime bug?

I am having a problem with php's DateTime functions.
Today is monday 3 december.
Assuming the following code:
$dte = new DateTime(date('Y-m-d H:i:s'));
var_dump($dte->format('Y-W'));
$dte->modify('+4 weeks');
var_dump($dte->format('Y-m-d H:i:s -- Y_W'));
$dte->modify('+1 days');
var_dump($dte->format('Y-m-d H:i:s -- Y_W'));
After four weeks it would be 31st of december. I would suspect to get the last week of the year (52?). But what I get is week 1 of 2012 as you can see in the following output.
string '2012-49' (length=7)
string '2012-12-31 14:48:00 -- 2012_01' (length=30)
string '2013-01-01 14:48:00 -- 2013_01' (length=30)
So my problem is that after the first modification I think I should get:
2012-12-31 14:48:00 -- 2012_52
but instead I get
2012-12-31 14:48:00 -- 2012_01
So why does the week go back to 01 without incrementing the year, and than why does the other line gives me 2013_01 ?
EDIT::
I now see that the week before is week 52, anything to do with leap year?
But then again, how can the week go back to 01 without incrementing the year?
So why does the week go back to 01 without incrementing the year, and than why does the other line gives me 2013_01 ?
I think you're displaying the "year" instead of the "week-year". When you're using week numbers, it's the week-year that's the relevant part; simple "year" is only relevant with respect to month and day.
EDIT: I think you want the o format specifier instead, so try:
var_dump($dte->format('Y-m-d H:i:s -- o_W'));
That should show you 2013_01 for December 31st 2012, as it's in week 1 of week-year 2013.
So basically, I don't think this is a bug in DateTime - it's just a misunderstanding of how "week of year" is meant to be used.
This seems to be no bug. According to the documentation W will return ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0) and because Mon, 31 Dec 2012 15:04:46 +0100 is Monday it will be 1 instead of 52.
Further information on Wikipedia and this nice site.

work out the date of the fourth saturday in the current month

Bit stuck about how to go about this one. Given the current month, I need to to return the date of the fourth saturday of each month.
e.g. This month would be Feb 20th, next would be March 27th.
Thanks
I'm not a PHP coder, however, it seems strtotime is what you're after.
You can use strtotime("fourth Saturday") and it will return the 4th saturday.
Check out the strtotime docs.
EDIT:
Just to make the answer complete, thanks to Tom and Paul Dixon
date('dS F',strtotime('Fourth Saturday '.date('F o')));
You can use strtotime to find "next saturday" based on a starting date. If that starting date is the day before the earliest possible preceding day (21st) we get the answer...
//required year/month
$yyyymm="2009-01";
//find next saturday after earliest possible date
$t=strtotime("next saturday", strtotime("{$yyyymm}-21"));
//here you go!
echo "4th saturday of $yyyymm is ".strftime("%Y-%m-%d",$t)."\n";
Earliest possible 4th repeat of a day in any month is the 22nd (1,8,15,22), last possible 4th repeat is 28th (7,14,21,28).
EDIT: Although it's not clear in the documentation, you can request the "fourth saturday" too - use the zeroth day of the month as the basis:
$t=strtotime("fourth saturday", strtotime("{$yyyymm}-00"));
or omit the basis time and specify the month and year directly:
$t=strtotime("fourth saturday feb 2009");
Tip of the hat to Robin "I'm not a PHP coder" Day for spotting that :)
The earliest date for the fourth Saturday is the 22nd of the month. So look at the 22nd, see what day of the week it is, if it's not Saturday, add one day to the date, and check again, until you find a match (maximum you would have to check is 6 days).
Find the first Saturday of the month, and then add three weeks to that.
If you don't know when the first Saturday is (or, rather, don't know specifically a date corresponding with a day name), you might want to look at the Doomsday algorithm, which I conveniently looked at for another post with a somewhat similar issue.
function fourth_saturday($year, $month)
{
$info = localtime(mktime(0, 0, 0, $month , 1, $year));
return 28 - $info[6];
}
in PHP rather than pseudo code (think requires 5.2)
$date = getdate();
$date-> setDate($date->format('Y'), $date->format('Y'), '1'); // 1st of month.
while ($date->format('w' != 6)
$date->modify("+1 day");
$date->modify("+21 day"); // date is now on the fourth saturday

Categories