views:

74

answers:

2

Hello there!

So basically, I'm currently selecting a Timestamp from my MySQL database. In the database, the timestamp looks like so:

2010-06-30 12:36:08

Obviously for a webapp, that's not very attractive for users to view. So, using some CodeIgniter functions, I made it look a bit nicer.

<h4 class="timestamp">
    <?php // Quickly calculate the timespan
    $post_date = mysql_to_unix($row->date);
    $now = time();
    echo timespan($post_date, $now);?> ago
</h4>

If you don't do CodeIgniter, everything's standard PHP except for echo timespan(). CodeIgniter just echoes it as an 'English' timespan. So, an example output would be:

2 Months, 4 Weeks, 5 Hours, 20 Minutes ago

That's all well and good, but, I want to make it seem nicer still... there are too many commas and its all a tad too long (I know, I'm picky...). What I'd like is:

  1. If the timespan is less than a day old, the output should be 7 hours, 33 minutes ago
  2. If the timespan is less than a week old, the output should be 4 days ago
  3. If the timespan is less than a month old, the output should be 2 weeks, 6 days ago
  4. If the timespan is over a month old, the output should be 4 months ago
  5. In the eventual case of the timespan being over a year old, the output should be Over a year ago

As you can see, I'm currently using a CodeIgniter function to simplify this - but if there's any native PHP function that can do what I want it to, that'll be awesome.

Thanks for your help!

Jack

+6  A: 

This is best done on the client side in the presentation layer. Here is a JS solution:

Timeago is a jQuery plugin that makes it easy to support automatically updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").

Timeago will turn all abbr elements with a class of timeago and an ISO 8601 timestamp in the title:

<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>

into something like this:

<abbr class="timeago" title="July 17, 2008">about a year ago</abbr>

To convert the date into the ISO 8601 format you can do something like this:

<?= date("c", $post_date) ?>

Examples:

You opened this page less than a minute ago. (This will update every minute. Wait for it.)

This page was last modified 11 days ago.

Ryan was born 31 years ago.

Bakkal
Thats supergreat, allows for caching.
Imre L
That's interesting, but it's not a PHP solution. Also the way it's worded, it's unclear what `date("c", $post_date)` has to do with anything (I even thought you were saying that was outputting what's below).
Artefacto
@Artefacto: it's because you didn't read the Timeago page. It works elements with a `class` of `timeago` and an ISO 8601 timestamp in the `title`. the `date()` PHP function call above yields an ISO 8601 format.
Bakkal
@Bak Of course I didn't :p
Artefacto
@Artefacto: I hope you see the need for the ISO 8601 format now. I think StackOverflow uses something similar: `<span title="2010-07-02 21:31:32Z" class="relativetime">52 mins ago</span>`
Bakkal
@Bak Yes, it's better now. +1
Artefacto
@Bak SO definitely does it server-side.
Artefacto
@Art: Yeah the SO is server-side since it doesn't change until we refresh the page. Seems their `title` field is just for the popup. I watched Joel's presentation about SO on Google TechTalk, seems they use jQuery, they should use Timeago xD
Bakkal
Cheers Bakkai, it might not be PHP-based but it's definitely the most efficient solution. Thanks!
Jack Webb-Heller
+1  A: 
$ts = new DateTime();
$ts->setTimestamp($my_timestamp);
$cur = new DateTime();
$difference = $cur->diff($ts);
if ($difference->format("%a") == 0)
    $out = $difference->format("%h hours %i minutes");
elseif ($difference->format("%a") < 7)
    $out = $difference->format("%a days");
elseif ($difference->format("%m") == 0) {
    $days = $difference->format("%a");
    $out = sprintf("%d weeks %d days", floor($days / 7),
        $days % 7);
}
elseif ($difference->format("%y") == 0)
    $out = $difference->format("%m months");
else
    $out = "over a year";

You'll have to make a few adjustments if you don't want stuff like "1 days".

Artefacto
1) Make it a function.
Imre L
@Imr That's trivial and is left as an exercise to reader.
Artefacto
Thanks, Artefacto for the PHP-based solution. Did you just write this off the top of your head, or had you seen this before? It's pretty clever.
Jack Webb-Heller
@Jack I wrote it especially for the occasion :)
Artefacto