PHP Dates and Times
Finding the Difference of Two Dates
Problem
You want to find the elapsed time between two dates. For example, you want to tell a user how long it’s been since she last logged on to your site.Solution
Create DateTime objects for each date. Then use the DateTime::diff() method to obtain a DateInterval object that describes the difference between the dates.Example Calculating the difference between two dates
// 7:32:56 pm on May 10, 1965
$first = new DateTime("1965-05-10 7:32:56pm",
new DateTimeZone('America/New_York'));
// 4:29:11 am on November 20, 1962
$second = new DateTime("1962-11-20 4:29:11am",
new DateTimeZone('America/New_York'));
$diff = $second->diff($first);
printf("The two dates have %d weeks, %s days, " .
"%d hours, %d minutes, and %d seconds " .
"elapsed between them.",
floor($diff->format('%a') / 7),
$diff->format('%a') % 7,
$diff->format('%h'),
$diff->format('%i'),
$diff->format('%s'));
Example prints:
The two dates have 128 weeks, 6 days, 15 hours, 3 minutes, and 45 seconds
elapsed between them.
Discussion
There are a few subtleties about computing date differences that you should be aware of. First of all, 1962 and 1965 precede the beginning of the Unix epoch. Because of the 600-billion year range of PHP’s built-in time library, however, this isn’t a problem.Next, note that the results of DateTime::diff() produce what a clock would say is the time difference, not necessarily the absolute amount of elapsed time. The two dates in Example are on different sides of a DST switch, so the actual amount of elapsed time between them is an hour less (due to the repeating clock-hour in the fall switch to standard time) than what’s shown in the output.
To compute elapsed time difference, build DateTime objects out of the epoch timestamps from each local timestamp, then apply DateTime::diff() to those objects, as shown in Example.
Example Calculating the elapsed-time difference between two dates
// 7:32:56 pm on May 10, 1965
$first_local = new DateTime("1965-05-10 7:32:56pm",
new DateTimeZone('America/New_York'));
// 4:29:11 am on November 20, 1962
$second_local = new DateTime("1962-11-20 4:29:11am",
new DateTimeZone('America/New_York'));
$first = new DateTime('@' . $first_local->getTimestamp());
$second = new DateTime('@' . $second_local->getTimestamp());
$diff = $second->diff($first);
printf("The two dates have %d weeks, %s days, " .
"%d hours, %d minutes, and %d seconds " .
"elapsed between them.",
floor($->format('%a') / 7),
$diff->format('%a') % 7,
$diff->format('%h'),
$diff->format('%i'),
$diff->format('%s'));
Example prints:
The two dates have 128 weeks, 6 days, 14 hours, 3 minutes, and 45 seconds
elapsed between them.
This, as you can see, is an hour different from the output of Example. The Date Time objects created with a format string of @ plus an epoch timestamp always have a time zone of UTC, so their difference is not affected by any daylight saving time or other local time adjustments.
At the time of writing, PHP Bug 52480 is outstanding, which affects some rare date interval calculations with certain hour values and time zone offsets. You can work around this bug by using UTC as the time zone for interval calculations.
No comments:
Post a Comment