Format a time interval with the requested granularity
This class, a refactored version of Drupal’s format_interval function, makes it relatively easy to format an interval value. The format will automatically format as compactly as possible. For example: if the difference between the two dates is only a few hours and both dates occur on the same day, the year, month, and day parts of the date will be omitted.
class DateIntervalFormat
{
/**
* Format an interval value with the requested granularity.
*
* @param integer $timestamp The length of the interval in seconds.
* @param integer $granularity How many different units to display in the string.
* @return string A string representation of the interval.
*/
public function getInterval($timestamp, $granularity = 2)
{
$seconds = time() - $timestamp;
$units = array(
'1 year|:count years' => 31536000,
'1 week|:count weeks' => 604800,
'1 day|:count days' => 86400,
'1 hour|:count hours' => 3600,
'1 min|:count min' => 60,
'1 sec|:count sec' => 1);
$output = '';
foreach ($units as $key => $value) {
$key = explode('|', $key);
if ($seconds >= $value) {
$count = floor($seconds / $value);
$output .= ($output ? ' ' : '');
if ($count == 1) {
$output .= $key[0];
} else {
$output .= str_replace(':count', $count, $key[1]);
}
$seconds %= $value;
$granularity--;
}
if ($granularity == 0) {
break;
}
}
return $output ? $output : '0 sec';
}
}
Usage:
$dateFormat = new DateIntervalFormat();
$timestamp = strtotime('2009-06-21 20:46:11');
print sprintf('Submitted %s ago', $dateFormat->getInterval($timestamp));
Outputs:
Submitted 3 days 4 hours ago
Cool. I wrote something similar to this a couple of weeks ago. The only differences being that the words for “day”, “month”, “year” etc were set as class properties so you could set externally and you could also set the date that you’re using as time() so you could measure betweek 2 specific dates if you wanted to.
I’d like to implement something for MySQL timestamps as well – I don’t really trust unix ones.
Jasper
June 25, 2009 at 7:26 am
[...] Cargnelutti has posted a class (DateIntervalFormat) that gives you the difference between a date and “now” in words [...]
Webs Developer
June 25, 2009 at 6:03 pm
Nice. Although I would have made the function static.
BigTrucK
June 25, 2009 at 8:46 pm
Static? Why?
Federico
June 25, 2009 at 10:43 pm
[...] Cargnelutti has posted a class (DateIntervalFormat) that gives you the difference between a date and “now” in words [...]
DreamNest
June 26, 2009 at 1:31 pm
You should do something with the explode(‘|’, $key) because it will done every time the function is called => If i call it 10 times the explode will be called 10 times per unit => 60 times! (perhaps hardcoded as a static array of class or function
Also I would prefer the use of a static method, that would also speed the class up
and last but not least i think i would prefer the strtotime-function inside of the getInterval-function so i don’t have to call it every time and save some annoying tipping ;)
Nzsz
June 28, 2009 at 8:38 pm
I really liked the idea you had, but for my purpose I had to change your class a bit. The first thing I changed was added support for PHP DateTime, including DateTimeZone so that the current date is compared correctly, I also changed the method so that a string with the current date can be passed (as Nzsz already mentioned).
The second thing I changed was the support for leap years. Currently your class does not support those years and will generate an incorrect day/.. count for years < 2008.
The other stuff is mostly for viewing pleasure, and to replace the names used.
http://www.pastebin.be/19456
Gerard Klomp
June 29, 2009 at 11:15 am
Indeed, a year may contain one or more extra days. I guess for those who want more precision, then yes, it is important to take the leap year into consideration.
Thanks.
Federico
June 29, 2009 at 6:26 pm
Hello,
nice code, thanks. I’ve ported it to perl, with some modifications. Have a look at
http://dpaste.org/RO8C/
if you’re interested.
Jonas
October 8, 2010 at 4:05 pm