Just a quick note to refine a function that will take a date in the past and return the number of years, months, weeks, days, hours, minutes and seconds.
Why?
Here are some examples of what we want to achieve:
1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds // full string 1 year 3 weeks 5 hours 7 seconds // where shown values are not zero
- 1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds  // full string
- 1 year 3 weeks 5 hours 7 seconds  // where shown values are not zero
3 days ago // where event is 3 days ago or just over but less than 4 days ago 1 week ago // where event is just over 1 week ago but less than 2 weeks ago
- 3 days ago  // where event is 3 days ago or just over but less than 4 days ago
- 1 week ago  // where event is just over 1 week ago but less than 2 weeks ago
How?
I know there are so many examples out there that do this perhaps better but this one I understand and can customize to fit my needs.
This PHP function accepts as parameter a SQL date (or date format that strtotime() can convert) and outputs the largest unit (for example "1 year" not "1 year 2 months 3 days, etc...").
function getTimeAgo($p_Date) { // get seconds ago $v_Seconds = strtotime('now') - strtotime($p_Date); // set unit labels $a_UnitLabels = array('year','month','week','day','hour','minute','second'); // set unit values $a_UnitValues = array( floor($v_Seconds / 31536000), floor(($v_Seconds % 31536000) / 2592000), floor(($v_Seconds % 2592000) / 604800), floor(($v_Seconds % 604800) / 86400), floor(($v_Seconds % 86400) / 3600), floor(($v_Seconds % 3600) / 60), floor($v_Seconds % 60), ); // initiate array (for array_slice) $a_UnitPairs = array(); // loop concatenating unit value to its label for($i=0;$i<count($a_UnitLabels);$i++){ // pair up if greater than zero $v_Str = $a_UnitValues[$i]>0 ? $a_UnitValues[$i].' '.$a_UnitLabels[$i] : ''; // grammar for plural/singular (should always be a positive number) $v_Str .= $a_UnitValues[$i]>1 ? 's' : ''; // only add to array if not empty/zero if($v_Str!='') $a_UnitPairs[] = $v_Str; } // take first item of array (round up to largest unit) $v_ReturnStr = $a_UnitPairs[0].' ago'; // return return $v_ReturnStr; }
- function getTimeAgo($p_Date) {
- // get seconds ago
- $v_Seconds = strtotime('now') - strtotime($p_Date);
- // set unit labels
- $a_UnitLabels = array('year','month','week','day','hour','minute','second');
- // set unit values
- $a_UnitValues = array(
- floor($v_Seconds / 31536000),
- floor(($v_Seconds % 31536000) / 2592000),
- floor(($v_Seconds % 2592000) / 604800),
- floor(($v_Seconds % 604800) / 86400),
- floor(($v_Seconds % 86400) / 3600),
- floor(($v_Seconds % 3600) / 60),
- floor($v_Seconds % 60),
- );
- // initiate array (for array_slice)
- $a_UnitPairs = array();
- // loop concatenating unit value to its label
- for($i=0;$i<count($a_UnitLabels);$i++){
- // pair up if greater than zero
- $v_Str = $a_UnitValues[$i]>0 ? $a_UnitValues[$i].' '.$a_UnitLabels[$i] : '';
- // grammar for plural/singular (should always be a positive number)
- $v_Str .= $a_UnitValues[$i]>1 ? 's' : '';
- // only add to array if not empty/zero
- if($v_Str!='') $a_UnitPairs[] = $v_Str;
- }
- // take first item of array (round up to largest unit)
- $v_ReturnStr = $a_UnitPairs[0].' ago';
- // return
- return $v_ReturnStr;
- }
Usage
$v_Str = getTimeAgo('2019-05-16 19:30:00'); // If (at time of print) this date is 17 minutes and 5 seconds ago // then $v_Str = "17 minutes ago"
- $v_Str = getTimeAgo('2019-05-16 19:30:00');
- // if (at time of print) this date is 17 minutes and 5 seconds ago
- // then $v_Str = "17 minutes ago"
Or how about
$v_Str = getTimeAgo('-1 week 2 days 4 hours 2 seconds'); // yields "1 week ago" $v_Str = getTimeAgo('last Monday'); // yields "3 days ago" (it's Thursday) $v_Str = getTimeAgo('first day of this month'); // yields "15 days ago" (it's the 16th)
- $v_Str = getTimeAgo('-1 week 2 days 4 hours 2 seconds');
- // yields "1 week ago"
- $v_Str = getTimeAgo('last Monday');
- // yields "3 days ago" (it's Thursday)
- $v_Str = getTimeAgo('first day of this month');
- // yields "15 days ago" (it's the 16th)
The same PHP function as above but somewhat minimized
function getTimeAgo($p){ $s = strtotime('now') - strtotime($p); $a1 = array('year','month','week','day','hour','minute','second'); $a2 = array( floor($s/31536000), floor(($s%31536000)/2592000), floor(($s%2592000)/604800), floor(($s%604800)/86400), floor(($s%86400)/3600), floor(($s%3600)/60), floor($s%60), ); for($i=0;$i<count($a1);$i++){ $str = $a2[$i]>0 ? $a2[$i].' '.$a1[$i] : ''; $str .= $a2[$i]>1 ? 's' : ''; if($str!='') break; } return $str.' ago'; }
- function getTimeAgo($p){
- $s = strtotime('now') - strtotime($p);
- $a1 = array('year','month','week','day','hour','minute','second');
- $a2 = array(
- floor($s/31536000),
- floor(($s%31536000)/2592000),
- floor(($s%2592000)/604800),
- floor(($s%604800)/86400),
- floor(($s%86400)/3600),
- floor(($s%3600)/60),
- floor($s%60),
- );
- for($i=0;$i<count($a1);$i++){
- $str = $a2[$i]>0 ? $a2[$i].' '.$a1[$i] : '';
- $str .= $a2[$i]>1 ? 's' : '';
- if($str!='') break;
- }
- return $str.' ago';
- }
If you want the first 4 words but minified (eg. "1 week and 2 days ago"):
function getTimeAgo($p) { $s = strtotime('now') - strtotime($p); $a1 = array('year','month','week','day','hour','minute','second'); $a2 = array( floor($s / 31536000), floor(($s % 31536000) / 2592000), floor(($s % 2592000) / 604800), floor(($s % 604800) / 86400), floor(($s % 86400) / 3600), floor(($s % 3600) / 60), floor($s % 60), ); for($i=0;$i<count($a1);$i++){ $v = $a2[$i]>0 ? $a2[$i].' '.$a1[$i] : ''; $v .= $a2[$i]>1 ? 's' : ''; if($v!='') $a3[] = $v; } return implode(' and ', array_slice($a3,0,2)).' ago'; }
- function getTimeAgo($p) {
- $s = strtotime('now') - strtotime($p);
- $a1 = array('year','month','week','day','hour','minute','second');
- $a2 = array(
- floor($s / 31536000),
- floor(($s % 31536000) / 2592000),
- floor(($s % 2592000) / 604800),
- floor(($s % 604800) / 86400),
- floor(($s % 86400) / 3600),
- floor(($s % 3600) / 60),
- floor($s % 60),
- );
- for($i=0;$i<count($a1);$i++){
- $v = $a2[$i]>0 ? $a2[$i].' '.$a1[$i] : '';
- $v .= $a2[$i]>1 ? 's' : '';
- if($v!='') $a3[] = $v;
- }
- return implode(' and ', array_slice($a3,0,2)).' ago';
- }
When could I possibly want to do this? Well I've previously used this for password change reminders but on this occasion for a listing of reviews laid out as per the following screenshot: