<?
function counttime($start, $stop = false, $display = "combined", $short = false) {
# version 1.4
# Author: Jonas Eklundh Communication AB
require_once ("adodb_time.php");
if (!$stop) $stop = adodb_date("Y-m-d");
$result = [];
$sec["seconds"] = 1;
$sec["minutes"] = $sec["seconds"]*60;
$sec["hours"] = $sec["minutes"]*60;
$sec["days"] = $sec["hours"]*24;
$sec["weeks"] = $sec["days"]*7;
$sec["months"] = $sec["days"]*28; # 28 so "feb 01-feb 28" is considered one month
$sec["years"] = $sec["days"]*365; # 365 includes leap years
$sec = array_reverse($sec);
# make sure that $from is always the earliest date
$from = $stop > $start ? $start : $stop;
$to = $stop > $start ? $stop : $start;
# extract the parts of each date, for adodb_mktime
$fp = preg_split("/[ :-]/", $from);
$tp = preg_split("/[ :-]/", $to);
# get time
$target = adodb_mktime(($tp[3] ?? false), ($tp[4] ?? false), ($tp[5] ?? false), ($tp[1] ?? false), ($tp[2] ?? false), ($tp[0] ?? false));
$source = adodb_mktime(($fp[3] ?? false), ($fp[4] ?? false), ($fp[5] ?? false), ($fp[1] ?? false), ($fp[2] ?? false), ($fp[0] ?? false));
# the difference, in seconds, between the two dates
$diff = $target-$source;
if (in_array($display, array("combined", "array"))) {
unset($sec["weeks"]);
if ($diff >= $sec["years"]) {
#debug("YES: " . $diff);
#debug(adodb_date("Y-m-d", $source));
for ($y = adodb_date("Y", $source);$y <= adodb_date("Y", $target);$y++) {
$day = adodb_date("m-d", $source) == "02-29" ? 28 : $fp[2]; # considering feb 29, since we can't use it consistently
$comptime = adodb_mktime(($fp[3] ?? false), ($fp[4] ?? false), ($fp[5] ?? false), ($fp[1] ?? false), $day, $y); #stepping a full year into the future. i.e. same date
if ($comptime > $source && $comptime <= $target) {
# if comptime is within the range, a full year has elapsed
if (empty($result["years"])) $result["years"] = 0;
$result["years"]++; # so we add a year to the result
$diff = $target-$comptime; # and remove the time we're at from the diff
}
}
}
if ($diff >= $sec["months"] && $diff > 0) {
# Ok, the time left is at least one month long
$starttime = $target-$diff; # This is the second we're starting on
for ($i = $starttime;$i <= $target;$i+= $sec["days"]) {
$comp_day = adodb_date("d", $source); # This is the day of month we're comparing against
if ($comp_day > adodb_date("t", $i)) $comp_day = adodb_date("t", $i); #making sure we don't compare 31 jan to 31 feb
if (date("d", $i) == $comp_day && $i != $starttime) {
# It's the same day of month, so one month has passed
# So we subtract the aggregated time from the diff
$hour = $fp[3] ?? "00"; # if hour is specified, we need to use that as well
$diff = $target-strtotime(adodb_date("Y-m-$comp_day $hour:i", $i)); # setting diff to the amount of seconds so far
if (empty($result["months"])) $result["months"] = 0;
$result["months"]++; # and add one moth to the result.
}
}
}
# now diff every other type (i.e. days and hours)
foreach(explode(",", "days,hours,minutes") as $type) {
if ($diff >= $sec[$type]) {
$result[$type] = floor($diff/$sec[$type]);
$diff-= $result[$type]*$sec[$type];
}
}
if ($result){
if ($display == "array") return $result;
foreach($result as $type => $nr) {
$text = " " . oom($nr, lp(preg_replace("/s$/", "", $type) , "L") , lp($type, "L"));
$last = "and";
if ($short){
$text = preg_replace("/^s(.).*$/", "$1", $text);
$last = "&";
}
$out[] = "$nr$text";
}
return itemlist($out, ", ", $last);
} else {
return false;
}
}
elseif ($display == "months"){
if ($diff >= $sec["months"]){
# Ok, counting only months can be a bit tricky
$start = $source;
while (1){
$start += ($sec["days"]*35);
$start = adodb_mktime(0, 0, 0, adodb_date("m", $start), 1, adodb_date("Y", $start));
if ($start > $target) break;
if ($iterations++ > 200) break;
$result["months"]++;
}
return $result["months"];
} else {
return 0;
}
}
elseif ($display == "years"){
if ($diff >= $sec["years"]){
$start = $source;
$iterations = 0;
$result = [];
while (1){
$start += ($sec["days"]*366);
$start = adodb_mktime(0, 0, 0, adodb_date("m", $start), 1, adodb_date("Y", $start));
if ($start > $target) break;
if ($iterations++ > 200) break;
if (empty($result["years"])) $result["years"] = 0;
$result["years"]++;
}
return $result["years"];
} else {
return 0;
}
}
elseif ($display == "rounded"){
if ($diff < 60){
return lp("now");
}
foreach (array_reverse($sec) as $w => $s){
if ($diff < $s){
$nr = round($diff/$lasts, 0, PHP_ROUND_HALF_DOWN);
return $nr . SPACE . oom($nr, lp(preg_replace("/s$/", "", $lastw) , "L") , lp($lastw, "L")) . SPACE . lp("ago", "L");
}
$lasts = $s;
$lastw = $w;
}
}
elseif ($display == "roundedshort"){
if ($diff < 60){
return lp("now");
}
foreach (array_reverse($sec) as $w => $s){
$w = substr($w, 0, 1);
if ($diff < $s){
$nr = round($diff/$lasts, 0, PHP_ROUND_HALF_DOWN);
return $nr . $lastw;
}
$lasts = $s;
$lastw = $w;
}
}
elseif($sec[$display]) {
if ($display == "seconds") return $target - $source;
return (int)(($target-$source) /$sec[$display]);
}
}
?>
Note that the code is the exact code that I am using and may use functions that are exclusive to my system, and as such may not be suitable for copy/paste. Plus, these functions can change at any time and any blogs/tutorials that depend on these functioning in a specific way may have changed since it was written. If such a discrepancy is found, please email me at
If the function "lp()" is used, it's my "Language Print" function, that translates phrases from english to the site language. So, instead of "lp('and')" you would use just "and".
If the function "lp()" is used, it's my "Language Print" function, that translates phrases from english to the site language. So, instead of "lp('and')" you would use just "and".