2

I was going through a php code today and found this to be really weird.

<?php
  $now = new DateTime("2015-07-29 03:38:55");
  $previous = new DateTime("2013-07-29 05:06:40");
  $diff = $now->diff($previous);
  $diff2 = $previous->diff($now);

  printf("%d years, %d month, %d days, %d hours, %d minutes %d seconds.<br/>", $diff->y, $diff->m, $diff->d, $diff->h, $diff->i, $diff->s);
  printf('%d years, %d month, %d days, %d hours, %d minutes %d seconds', $diff->y, $diff->m, $diff2->d, $diff2->h, $diff2->i, $diff2->s);

The output is

1 years, 11 month, 30 days, 22 hours, 32 minutes 15 seconds

1 years, 11 month, 29 days, 22 hours, 32 minutes 15 seconds

I have two questions

  1. I read the document it said that $previous->diff($now); shows $now - $previous. However, if it is the other way around, wouldn't it be negative?

  2. Why is one 30 days and the other is 29 days?

2
  • If you only care about the absolute difference add use $diff = $now->diff($previous, true); Commented Jul 29, 2015 at 20:53
  • 1. Check the invert of the $diff which shows if the result negative. 2. Refer to this answer of this question for why the days is different. Commented Nov 25, 2019 at 2:08

2 Answers 2

1

I have a speculation that this could be due to the invert. I'm not entirely sure why it is adding an extra day... but a quick change I did was:

$now = new DateTime("2015-07-29 03:38:55");
$previous = new DateTime("2013-07-29 05:06:40");

$diff = $now->diff($previous);
$diff2 = $previous->diff($now);

printf("%d years, %d month, %d days, %d hours, %d minutes %d seconds\r\n", $diff->y, $diff->m, ($diff->d - $diff->invert), $diff->h, $diff->i, $diff->s);
printf('%d years, %d month, %d days, %d hours, %d minutes %d seconds', $diff->y, $diff->m, ($diff2->d - $diff2->invert), $diff2->h, $diff2->i, $diff2->s);

And the output is:

1 years, 11 month, 29 days, 22 hours, 32 minutes 15 seconds
1 years, 11 month, 29 days, 22 hours, 32 minutes 15 seconds

Or, alternatively, the above is completely wrong and is just a coincidence... another explanation may be that the diff days was a float value for $diff, and so it was rounded down... yielding 29 days. Possible leap-year issue as well.

Edit

The above is also wrong... if you change the output to floats, it will show whole numbers. This adds to the confusion. I'll leave this answer to possibly help someone else figure out the solution.

$now = new DateTime("2015-07-29 03:38:55", new DateTimeZone('GMT'));
$previous = new DateTime("2013-07-29 05:06:40", new DateTimeZone('GMT'));

$diff = $now->diff($previous);
$diff2 = $previous->diff($now);

printf("%f years, %f month, %f days, %f hours, %f minutes %f seconds %f total days\r\n", $diff->y, $diff->m, $diff->d, $diff->h, $diff->i, $diff->s, $diff->days);
printf('%f years, %f month, %f days, %f hours, %f minutes %f seconds %f total days', $diff->y, $diff->m, $diff2->d, $diff2->h, $diff2->i, $diff2->s, $diff2->days);

I even set the timezone in hopes to help. Still yields whole numbers:

1.000000 years, 11.000000 month, 30.000000 days, 22.000000 hours, 32.000000 minutes 15.000000 seconds 729.000000 total days
1.000000 years, 11.000000 month, 29.000000 days, 22.000000 hours, 32.000000 minutes 15.000000 seconds 729.000000 total days
Sign up to request clarification or add additional context in comments.

2 Comments

If $now = 2015-07-29 04:38:53 and $previous = 2013-07-29 04:38:54 output for first one is 1 years, 11 month, 30 days, 23 hours, 59 minutes 59 seconds and for the second one is 1 years, 11 month, 29 days, 23 hours, 59 minutes 59 seconds. However if $now= $previous except for the year. Both of the output are the same.
I was thinking there might be a DST bug as well... but I can't confirm.
0
  1. the sign of the difference is in the invert property: $diff->invert=1 and $diff2->invert=0
  2. You can see in the php source here a day correction by 1 when:
    1. the 1st of the dates is in DST and the 2nd is not
    2. the timestamp of the 2nd date starts after the timetstamp of the 1st one without the DST correction
    3. the timestamp of the 2nd date starts before the timetstamp of the 1st one with the DST correction

This is what is causing one to show 30 days and the other to show 29. In @Half Crazed's example, both dates are in DST, so no correction there. If the previous date of the OP were 2013-07-29 03:06:40, their wouldn't be a difference

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.