thara Posted September 26, 2012 Share Posted September 26, 2012 Hi.. everyone! I've noticed that Facebook, Twitter, and lots of other sites are using a relative date and time string description for user posts and comments. For example, "comment written about 3 months ago" instead of "comment written on September 20, 2012." I decided to do the same thing on my site. In my site I need to display 1 day ago, 2 days ago, 3 days ago,...... 1 week ago, 2 weeks ago, .... 1 months ago, 2 months ago, ...... 1 year ago, 2 years ago... etc. Already I have got user registered date and need to check it with current date and time and need to diplay it with above style on my home page. In my database, user registered date format is like this .. '2012-09-23 09:11:02' can anybody help me to build this script... and it will greatly appriciated. Thank you. Quote Link to comment Share on other sites More sharing options...
kicken Posted September 26, 2012 Share Posted September 26, 2012 You'll want to find the difference between the current date and the posting date, in seconds. The easiest way to do that is to convert them to a unix timestamp and just subtract the two. You can use the UNIX_TIMESTAMP function in your MySQL query, or PHP's strtotime() to convert a date to a unix timestamp. After that you just convert the # of seconds into your textual string. There are lots of implementations of functions for this if you search google, or you can try writing your own. Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 you may also want to check out the DateTime objects http://php.net/manual/en/book.datetime.php and DateInterval objects too http://php.net/manual/en/dateinterval.format.php Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 thanks for response... I tried with this function. But second and minutes not working there... $postedDateTime = '2012-09-23 09:11:02'; //$postedDateTime = date('2012-09-23 09:11:02'); function time_elapsed_since($postedDateTime){ $time = time() - strtotime($postedDateTime); // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } } echo 'Mr. Tharanga added his tutor profile ' . time_elapsed_since($postedDateTime) . ' ago'; any comments are greatly appreciated. Thank you. Quote Link to comment Share on other sites More sharing options...
kicken Posted September 26, 2012 Share Posted September 26, 2012 You're returning to early. Inside your foreach loop you want to concatenate each of the parts together to build a string, then return the string at the end of the function. Right now you will only see the largest segment because you return right away after generating it. Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 I am not clear with your answer. can you kindly explain it with an example? Thank You.. Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 (edited) Im calling it something like this.. include('includes/time_elapsed_since.php'); while ( $row = @mysqli_fetch_array ( $r, MYSQLI_ASSOC )) { // some coding.... echo ' <span>('; echo time_elapsed_since($addedDate); echo ' ago)</span>'; } Edited September 26, 2012 by thara Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 Like @kicken mentioned, don't return early and concatenate the results. $str = ''; foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); $str .= $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } return $str; Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 I added it to my function.. then its output is like this ... (1 month4 weeks30 days735 hours44136 minutes2648173 seconds ago) this is not my expecting result.. Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 (edited) You need to reduce time by the units "consumed" each time through the loop foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); $res .= sprintf('%d %s ', $numberOfUnits, $text ); $time %= $unit*$numberOfUnits; } return $res; Edited September 26, 2012 by Barand Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 Im sorry... actually I can not understand what you are saying.. I tried my best to fix this problem but still couldn't get to work it... tell me where im going wrong.. Thank you. Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 using the amendment I gave you I get Now: 2012-09-26 16:22:27 Posted date/time: 2012-09-23 09:11:02 3 day 7 hour 11 minute 25 second ago Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 (edited) That is because your function/calculation is wrong. @kicken and I just pointed out to get the X months Y weeks Z days .. you needed to concatenate the results. The correct calculation goes something like: function time_elapsed_since($postedDateTime) { $diff = abs(time() - strtotime($postedDateTime)); // to get the time since that moment $years = (int) $years = $diff / 31536000; $months = (int) $months = ($diff % 31536000) / 2592000; $weeks = (int) $weeks = (($diff % 31536000) % 2592000) / 604800; $days = (int) $days = ((($diff % 31536000) % 2592000) % 604800) / 86400; $hours = (int) $hours = (((($diff % 31536000) % 2592000) % 604800) % 86400) / 3600; $minutes = (int) $minutes = ((((($diff % 31536000) % 2592000) % 604800) % 86400) % 3600) / 60; $seconds = (int) $seconds = (((((($diff % 31536000) % 2592000) % 604800) % 86400) % 3600) % 60); return ($years ? $years .' years ' : ''). ($months ? $months .' months ' : ''). ($weeks ? $weeks .' weeks ' : ''). ($days ? $days .' days ' : ''). ($hours ? $hours .' hours ' : ''). ($minutes ? $minutes .' minutes ' : ''). ($seconds ? $seconds .' seconds ' : ''); } The very verbose format can be shortened. Something like: echo time_elapsed_since('+9876 minutes'); Returns: 6 days 20 hours 36 minutes Much easier is it of course to simply: $diff = new DateTime(new DateTime('+9876 minutes')); Which returns a DateInterval and has several properties to get the number of seconds/minutes/hours/.. http://php.net/manual/en/class.dateinterval.php Or use Carbon: echo (new Carbon)->diffForHumans(new Carbon('+9876 minutes')); Edited September 26, 2012 by ignace Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 ignace: His calculation was almost correct, he just wasn't reducing the elapsed time on each iteration as my code does with $time %= $units * $numberOfUnits; As you can see by my result, it works Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 (edited) thanks for all answers. both coding work for me.. But another problem encountered me when I use my earlier function. I used it for display 1 output. like 1 day ago, 1 week ago, 2 months ago.. .etc. this is my function again... <?php function time_elapsed_since ($addedDate){ $time = time() - strtotime($addedDate); // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } } ?> This function is work for weeks and months. that mean if a profile has added before 3 weeks, the output display correctly as '3 weeks ago' as well as if a profile has added before 2 months, the output display it as '2 months ago' etc. And just now I added a profile to my website to check seconds and minutes work like that . But there, not display '1 second ago, 2 seconds ago, or 1 minute ago, 3 minutes ago.. etc. Its only display string 'ago'. can you tell me what is the mistake for it.. any comments would be greatly appreciated. Thank you. Edited September 26, 2012 by thara Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 (edited) @barand sorry, my apologies, that was a response to thara, it just was posted with a bad timing apparently IPB does not always report when new content was added and I didn't check due to this handy feature. Edited September 26, 2012 by ignace Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 (edited) thara: your function worked for me Now: 2012-09-26 17:25:40 Posted date/time: 2012-09-26 17:25:02 38 seconds ago and a little later Now: 2012-09-26 17:29:00 Posted date/time: 2012-09-26 17:25:02 3 minutes ago Edited September 26, 2012 by Barand Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 (edited) Barand please check this again.. $date = '2012-09-26 17:25:02'; $postedDateTime = strtotime($date); //$postedDateTime = date('2012-09-23 09:11:02'); //$postedDateTime = strtotime('2012-09-25 09:11:02'); function time_elapsed_since ($postedDateTime){ $time = time() - $postedDateTime; // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } } echo 'Mr. Tharanga added his tutor profile ' . time_elapsed_since($postedDateTime) . ' ago'; ?> my output is "Mr. Tharanga added his tutor profile ago" NOTE: im trying on local host using wamp server.. Edited September 26, 2012 by thara Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 (edited) We have mentioned like 3 times now that you are exiting too early and you need to concatenate the output.. Edited September 26, 2012 by ignace Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 (edited) Your latest function: function time_elapsed_since ($postedDateTime){ $time = time() - $postedDateTime; // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } } echo 'Mr. Tharanga added his tutor profile ' . time_elapsed_since('+38 minutes') . ' ago'; Returns Mr. Tharanga added his tutor profile 42 years ago You need to subtract the $unit's from $time as per Barand's comment but apparently you don't want to listen/be helped. Edited September 26, 2012 by ignace Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 I declared this variable to above the function... with a value. $date = '2012-09-26 17:25:02'; $postedDateTime = strtotime($date); the output is "Mr. Tharanga added his tutor profile ago" but Barand has mentioned it is working properly.. Just I check it on live.. but the result is same. Quote Link to comment Share on other sites More sharing options...
ignace Posted September 26, 2012 Share Posted September 26, 2012 I give up! I won't help you anymore. Quote Link to comment Share on other sites More sharing options...
Barand Posted September 26, 2012 Share Posted September 26, 2012 Barand please check this again.. $date = '2012-09-26 17:25:02'; $postedDateTime = strtotime($date); //$postedDateTime = date('2012-09-23 09:11:02'); //$postedDateTime = strtotime('2012-09-25 09:11:02'); function time_elapsed_since ($postedDateTime){ $time = time() - $postedDateTime; // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':''); } } echo 'Mr. Tharanga added his tutor profile ' . time_elapsed_since($postedDateTime) . ' ago'; ?> my output is "Mr. Tharanga added his tutor profile ago" NOTE: im trying on local host using wamp server.. I got Now: 2012-09-26 18:00:45 Mr. Tharanga added his tutor profile 35 minutes ago Note: I added the Now: bit Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 Thanks for your time... But I dont know why I cant get the result. I tried again but nothing happen to earlier result. seconds and minutes can't get to display. Quote Link to comment Share on other sites More sharing options...
thara Posted September 26, 2012 Author Share Posted September 26, 2012 (edited) I give up! I won't help you anymore. I dont know why.. is this a silly question.? Edited September 26, 2012 by thara Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.