Error to calculate date diff with DateTime class - php

i'm trying to use the class DateTime (php>=5.3) to calculate difference from 2 date.
The example from the manual is simple and clear, i tried that example and work good.
But if a change the start and end date, there a problem:
$this->start_date = '2011-03-01';
$this->end_date = '2011-03-31';
var_dump($this->start_date, $this->end_date);
$datetime1 = new DateTime($this->start_date);
$datetime2 = new DateTime($this->end_date);
$interval = $datetime2->diff($datetime1);
echo $interval->format('%a total days')."\n";
echo $interval->format('%m month, %d days');
Output is:
30 total days //ok
1 month, 2 days //no! i think it should be 0 month, 30 days
With march don't work very well! :)

Aren't there 28 days in February? It might be picking February for the "month" unit for some reason or other. The PHP documentation for the method seems to suggest this kind of thing could easily be the case. Saying "x Months" isn't overly useful anyway as a month isn't a fixed unit, it could be 28, 29, 30 or 31 days.
Extract from the PHP dateinterval format documentation below.
The DateInterval::format() method does
not recalculate carry over points in
time strings nor in date segments.
This is expected because it is not
possible to overflow values like "32
days" which could be interpreted as
anything from "1 month and 4 days" to
"1 month and 1 day".

Related

PHP doesn't give a proper output for month substraction

Code:
$time = strtotime('2020-03-31');
echo date('Y-m-d', strtotime('-1 month', $time));
Expected Result: Any date from Feb 2020
Actual Result: 2020-03-02
Is there any better way to add or subtract a month from a given date?
Months are an awkward interval to work with, because they don't have a fixed length. Should the algorithm assume that by "1 month" you mean "30 days", or "31 days", or should it just try subtracting 1 from the "month" field in the date structure?
The last option is what is happening here: given "2020-03-31", PHP's date library is subtracting 1 from the "03" to give "2020-02-31". Since that's an invalid date (February 2020 had 29 days), it then "normalises" it to a real date - 2 days after the 29th February was the 2nd March.
Probably you want to use a more specific period to subtract, like 30 days - although note that if the initial input is "2020-03-01" that will give you "2020-01-31", not "2020-02-01".
Ultimately, this is a problem with our irregular calendar, rather than with PHP. It's really up to you to define what you mean by "a month before", and use a more specific algorithm that captures that requirement.
You can make code like below
<?php
$time = strtotime('2020-03-1 -32 days');
echo date('M-Y', $time); // output Feb-2020
?>
The above code will return date as you expected

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"

DateTime, +1 week and -1 week not working the same

I have a couple of functions juggling back and forth with weeks.
One surprising, and unwanted, behavior I discovered was this:
$date = new DateTime();
$date->setISODate(2014, 52);
$date->modify('+1 week');
echo date('YW', $date->getTimestamp()) . '<br />';
$date->setISODate(2014, 01);
$date->modify('-1 week');
echo date('YW', $date->getTimestamp()) . '<br />';
This code prints:
201401
201352
My expectation was:
201501
201352
Three questions:
1) Have I done something wrong in the code above or is there an inconsistent behavior between "+1 week" and "-1 week" (as in year not being stepped in the first case)?
Answer from comment:
It never increase/decrease year but week 1 happens to start in December 2013 thus it seems like it decrease year in the "-1 week" example.
2) If there is an inconsistency, can I trust the code will work the same on various platforms and PHP versions?
Answer:
No inconsistency (see accepted answer)
3) Is there a better way to step 1 week backward and forward in time (input is year and week, output is also year and week)?
bonus question) If there actually is an inconsistency, does anyone know why?
Answer:
No inconsistency, see answer on number 1 for explanation
Y is year from the date
o is ISO-8601 year number
W is ISO-8601 week number of year
if using 'W' for the week number use 'o' for the year.

PHP DateTime->diff dont works as expected [duplicate]

i'm trying to use the class DateTime (php>=5.3) to calculate difference from 2 date.
The example from the manual is simple and clear, i tried that example and work good.
But if a change the start and end date, there a problem:
$this->start_date = '2011-03-01';
$this->end_date = '2011-03-31';
var_dump($this->start_date, $this->end_date);
$datetime1 = new DateTime($this->start_date);
$datetime2 = new DateTime($this->end_date);
$interval = $datetime2->diff($datetime1);
echo $interval->format('%a total days')."\n";
echo $interval->format('%m month, %d days');
Output is:
30 total days //ok
1 month, 2 days //no! i think it should be 0 month, 30 days
With march don't work very well! :)
Aren't there 28 days in February? It might be picking February for the "month" unit for some reason or other. The PHP documentation for the method seems to suggest this kind of thing could easily be the case. Saying "x Months" isn't overly useful anyway as a month isn't a fixed unit, it could be 28, 29, 30 or 31 days.
Extract from the PHP dateinterval format documentation below.
The DateInterval::format() method does
not recalculate carry over points in
time strings nor in date segments.
This is expected because it is not
possible to overflow values like "32
days" which could be interpreted as
anything from "1 month and 4 days" to
"1 month and 1 day".

Month by week of the year?

I'm trying to get the number of the month of the year by the number of a week of the year and the year.
So for example week 1 is in january and returns 1, week 6 is in february so I want 2.
I tried to go with date_parse_from_format('W/Y') but had no success (it's giving me errors).
Is there any way to go with date_parse_from_format() or is there another way?
print date("m",strtotime("2011-W6-1"));
(noting that in 2011, January has six weeks so week 6 (by some definitions) is in month 1).
Just wanted to add a note for the first answer, the week number should be 01-09 for Weeks 1 through 9 (it will always give month 1 if you don't add the leading zero)
date("m",strtotime("2011-W06-1"));
Using PHP DateTime objects (which is the preferred way of dealing with dates see links below for more info) you can accomplish it this way:
$dateTime = new \DateTime();
$dateTime->setISODate($year,$week);
$month = $dateTime->format('n');
Note that the following will not work as week "W" is not a supported format:
$month = \DateTime::createFromFormat("W/Y ", "1/2015")->format('n');
The format used by this method is the same supported by the function you where trying to use date_parse_from_format, hence the errors.
Why PHP DateTime Rocks
DateTime class vs. native PHP date-functions
strtotime notes
PHP/Architect's Guide to Date and Time Programming (Chapter 2)
Something like this will do, this is also tested and works:
function getMonthByNumber($number,$year)
{
return date("F",strtotime('+ '.$number.' weeks', mktime(0,0,0,1,1,$year,-1)));
}
echo getMonthByNumber(27,2011);
Hope this helps

Categories