Problem in understanding datetime difference and invert - php

I am having a problem in understanding the difference between datetime. I am using PHP datetime class.
Here is a small part of my code to calculate the datetime difference:
date_default_timezone_set("Asia/Kolkata");
function timeline_date($date)
{
$today = new DateTime();
$timeline_date = new DateTime($date);
$interval = $today->diff($timeline_date);
echo "<pre>";
print_r($today);
print_r($timeline_date);
print_r($interval);
echo "</pre>";
}
$date = "2019-02-02 04:36:02";
echo timeline_date($date);
What is the meaning of statement:
$interval = $today->diff($timeline_date);
Is it subtracting $timeline_date from $today?
Or is it subtracting $today from $timeline_date?
I am having a great confusion regarding this particular statement. I searched on Internet but nothing is clearly mentioned on it.
Also $timeline_date can be past or future date and even today's date. So does it matter we should subtract small quantity from large quantity?
I get following output from above code:
DateTime Object
(
[date] => 2019-02-05 16:11:37
[timezone_type] => 3
[timezone] => Asia/Kolkata
)
DateTime Object
(
[date] => 2019-02-02 04:36:02
[timezone_type] => 3
[timezone] => Asia/Kolkata
)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 3
[h] => 11
[i] => 35
[s] => 35
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 1
[days] => 3
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
We can see [invert] => 1 in above array. What is actual meaning of it? If I change the $date to:
$date = "2019-02-10 04:36:02";
Then [invert] => 0 changes to 1. Why? Does it mean if we have past date in difference then invert will be 0 and if we have future date then this array element will be 1?

DateTime::diff gives you the difference between the two dates, somewhat obviously. It doesn't really matter which one is bigger or smaller, a delta is a delta regardless of that. However, the resulting DateInterval object does note which one was bigger or smaller with the DateInterval::$invert property:
Is 1 if the interval represents a negative time period and 0 otherwise. See DateInterval::format().
The rule is if $b in $a->diff($b) is before $a, $invert is 1. Looking at said DateInterval::format, you'll see:
R Sign "-" when negative, "+" when positive
r Sign "-" when negative, empty when positive
So, if you do care about the future/past difference, you can use the %R/%r formatting parameters in DateInterval::format to output a "-" and/or "+". If you don't care, just omit that option and it's irrelevant.

Related

DateTime diff returns me 0 when the compared DateTimes are different

I would like to return the hours and minutes of difference between two dates. The problem is that the result of the diff method returns me a diff of 0 (same DateTimes).
Here is my actual code :
$last_vote_date = new DateTime(\Auth::user()->last_vote_at);
$next_vote_date = $last_vote_date;
$next_vote_date->add(new DateInterval('PT3H'));
$diff = $next_vote_date->diff($last_vote_date, true);
$vote_hours = $diff->format('%h h %I m');
I debugged my vars. $last_vote_date is the correct DateTime.
$next_vote_date is a correct DateTime representing the last vote date + 3 hours.
However all the properties of the DateInterval object that diff returns are all 0 :
DateInterval Object ( [y] => 0 [m] => 0 [d] => 0 [h] => 0 [i] => 0 [s] => 0 [f] => 0 [weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 [invert] => 0 [days] => 0 [special_type] => 0 [special_amount] => 0 [have_weekday_relative] => 0 [have_special_relative] => 0 )
I really don't understand what's going wrong as my two DateTime objects being compared are different and are exactly the value I want.
When you do $next_vote_date = $last_vote_date you are basically copying a reference. Meaning any changes you make to $next_vote_date will affect $last_vote_date. The quick way to deal with this is to copy the object:
$last_vote_date = new DateTime(\Auth::user()->last_vote_at);
$next_vote_date = clone $last_vote_date;
$next_vote_date->add(new DateInterval('PT3H'));
$diff = $next_vote_date->diff($last_vote_date, true);
$vote_hours = $diff->format('%h h %I m');

Simple date_diff off significantly [duplicate]

This question already has answers here:
How to calculate the difference between two dates using PHP?
(34 answers)
Closed 5 years ago.
I'm trying to use date_diff to compare two dates, but it's not even coming close to the right number. To troubleshoot, I'm doing a simple hard-coded test:
$date1 = date_create("2014-03-20");
$date2 = date_create("2017-11-13");
$diff = date_diff($date1,$date2);
echo $diff->format('%r%d');
This outputs "24" for me -- so it's not even in the ballpark. Any ideas what's going wrong here?
The $diff outcome contains a DateInterval object. It contains the following:
DateInterval Object
(
[y] => 3
[m] => 7
[d] => 24
[h] => 0
[i] => 0
[s] => 0
[f] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 1334
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
By echo'ing $diff->d you'll get the day difference. If you'd like to have the total amount of days. Use $diff->days. Just play around with it.
You are using format codes for dates in PHP, but yet you are having a date interval, that has different format codes.
echo $diff->format('%y-%m-%d');
This will show the correct value.
If you are looking for the total number of days you should use the a format character. See more at php date interval format.
$diff->format('%a');
output:
1334

How to calculate time difference between SQL time and PHP time

I have set times in SQL in this format: 2016-01-03 12:13:26.
I would like to calculate the number of hours and minutes (if hours<1) going from NOW() to that particular SQL time.
I've been looking at all the different threads here but I can't seem to grasp how to convert PHP different time formats to SQL's.
This is the code I've been using, but this will only give me back hours up to 12, and minutes also. Don't know how to use it with days.
$now = date("d/m/Y h:i:s");
$commentime = strtotime($SQLTIME);
$timetocomment = $now - $commentime;
For instance, this code will yield "12 hours ago" for data I posted 24 hours ago to SQL.
How can I do it? Thank you.
This is my suggestion to use date() in this format date("Y-m-d h:i:s"). Than you will get the complete difference in an array.
function dateDifference($date_1 ,$date_2)
{
$datetime1 = date_create($date_1);
$datetime2 = date_create($date_2);
$interval = date_diff($datetime1, $datetime2);
return $interval;
}
$now = date("Y-m-d h:i:s");
$sqlTime = "2016-01-03 12:13:26";
$DateDiffArr = dateDifference($now,$sqlTime);
echo "<pre>";
print_r($DateDiffArr);
Result Is:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 22
[i] => 45
[s] => 55
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 1
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
In resultant array, you can get the all difference as you need like in years, months, days, minutes, seconds etc.

php interval and timezone

I would like to get the date time interval between two dates in a time zone that uses daylight savings time.
The following snipet shows the problem.
$timezone = new DateTimeZone('UTC');
$from_date_obj = DateTime::createFromFormat('Y-m-d H:i:s', '2014-10-31 23:59:59',$timezone);
$to_date_obj = DateTime::createFromFormat('Y-m-d H:i:s', '2014-11-20 23:47:02',$timezone);
$interval = $from_date_obj->diff($to_date_obj, TRUE);
print_r($interval);
For UTC timezone this shows:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 19
[h] => 23
[i] => 47
[s] => 3
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 19
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
Now this one:
$timezone = new DateTimeZone('America/Los_Angeles');
$from_date_obj = DateTime::createFromFormat('Y-m-d H:i:s', '2014-10-31 23:59:59',$timezone);
$to_date_obj = DateTime::createFromFormat('Y-m-d H:i:s', '2014-11-20 23:47:02',$timezone);
$interval = $from_date_obj->diff($to_date_obj, TRUE);
print_r($interval);
shows:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 20
[h] => -1
[i] => 47
[s] => 3
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 19
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
the one in UTC shows 19 days/23 hours/47 minutes and 3 seconds. The one for PT shows 20 days/-1 hours/47 minutes and 3 seconds. I think the right answer for PT should be 20 days/0 hours/47 minutes and 3 seconds.
Is there any way to do a diff in the pacific time zone and not end up with the negative hour? Is the -1 hours indication the desired result and what does it mean exactly?
update: I found out that indeed PHP doesn't seem to handle the diff with respect to DST which is discussed here:
PHP's DateTime::Diff gets it wrong?
As far as the results I was getting it appears to be a PHP bug as indicated in the above link.
There are two issues raised here:
One has to do with the difference between two dates and times when there is a clock change due to DST (Daylight Savings Time). In reality the difference between two dates and times should take into account the clock change, but apparently it does not.
That is documented pretty well in the following link:
PHP's DateTime::Diff gets it wrong?
Further I am chalking up the -1 problem as a php bug. Since PHP doesn't handle the DST changes between two date times anyway, and in my case the difference without taking DST into effect is close enough anyway, I will just do the diff calculation in UTC.
What php version are you using ? Im getting this result for 2nd code block -
DateInterval Object (
[y] => 0
[m] => 0
[d] => 19
[h] => 23
[i] => 47
[s] => 3
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 19
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
both of the codes should display the same result as your comparing the same date with just different timezone each time
Even after 8 years it is still not supported:
$day = \DateTime::createFromFormat('Y-m-d', '2023-03-26', new \DateTimeZone('Europe/Budapest'));
$followingDay = \DateTime::createFromFormat('Y-m-d', $day->format('Y-m-d'), new \DateTimeZone('Europe/Budapest'));
$followingDay->add(new \DateInterval('P1D'));
$day2 = \DateTime::createFromFormat('Y-m-d', '2023-03-27', new \DateTimeZone('Europe/Budapest'));
var_dump($day->getTimestamp(), $followingDay->getTimeStamp(), $day2->getTimeStamp());
var_dump($day, $followingDay, $day2);
Not to mention that it adds current time instead of 00:00:00 which I read in the documentation, so better to be careful. Though I generally hate PHP because of the low quality documentation, so I almost always write automated tests when I use a built-in function. It is full of bugs or undocumented behavior.
int(1679794696)
int(1679881096)
int(1679877496)
class DateTime#397 (3) {
public $date =>
string(26) "2023-03-26 03:38:16.000000"
public $timezone_type =>
int(3)
public $timezone =>
string(15) "Europe/Budapest"
}
class DateTime#404 (3) {
public $date =>
string(26) "2023-03-27 03:38:16.000000"
public $timezone_type =>
int(3)
public $timezone =>
string(15) "Europe/Budapest"
}
class DateTime#399 (3) {
public $date =>
string(26) "2023-03-27 02:38:16.000000"
public $timezone_type =>
int(3)
public $timezone =>
string(15) "Europe/Budapest"
}

How to get aggregate days from PHP's DateTime::diff?

$now = new DateTime('now');
$tomorrow = new DateTime('tomorrow');
$next_year = new DateTime('+1 year');
echo "<pre>";
print_r($now->diff($tomorrow));
print_r($now->diff($next_year));
echo "</pre>";
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 10
[i] => 17
[s] => 14
[invert] => 0
[days] => 6015
)
DateInterval Object
(
[y] => 1
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] => 6015
)
any ideas why 'days' shows 6015? why won't it show the total number of days? 1 year difference means nothing to me, since months have varying number of days.
A more appropriate bug report to follow would be #51184 which focuses on the problem of Windows reporting 6015 days (non-Windows appears OK).
No feedback has been given as yet with regards to whether the fix for #49778 (which deals with a different issue) affects this or if the problem persists. If anyone here could take a look and provide some feedback, that would be very kind of you.
Please upgrade to the latest php. This error only occurs on php 5.3 VC6.
$now = new DateTime('now');
should be
$now = new DateTime(''2010-01-01 00:00:00'');
more in the manual
http://nl3.php.net/manual/en/datetime.diff.php
Ok, looks like http://bugs.php.net/bug.php?id=49778 is the issue here.
its a bug
http://bugs.php.net/bug.php?id=49778
Thank you for your bug report.
Days is indeed not set when creating a DateInterval using the
constructor. A complication with this is that it is impossible to
determine the number of days when months or years are specified, since
these vary in length. It is possible to fill in the days field in some
cases and leave it 0 in others. In any case, it should be documented
that the days field is not always available.

Categories