News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

Friendly Time

Started by Louis (CSpotkill), March 05, 2005, 10:12:52 PM

Previous topic - Next topic

Louis (CSpotkill)

Link to Mod

Install this mod to make forum dates & times easier to understand:

  • Displays the current time in plain English. (Almost half past eight in the evening of March 5th, 2005)
  • Calculates fuzzy relative time for posts/PMs. (An hour ago or Saturday, last week)

See the mod in action at www.cszen.com

To install this mod (and many others): Download FriendlyTime1.1.zip. Click Admin, then click Package Manager, then Download New Packages. Under Upload a Package, click Browse and find the FriendlyTime1.1.zip. Then click Upload and follow the prompts.

Note: Only tested with SMF 1.0.2 - The modification should work in previous versions, but the installer might not. If you get any problems, please reply with your SMF/Friendly Time version numbers, and I'll try to fix the problems as soon as possible.

Also: This may not work in every locale and uses hard-coded English strings. However, modifying Friendly Time to work with other languages shouldn't be all that difficult. If I receive a translation for Friendly Time, I'll write the necessary localization code. Any code contributions welcome.

And something I forgot to mention in the "Readme": You must have Today & Yesterday enabled for this modification to work correctly. Don't worry - if you haven't disabled it, it's enabled. Otherwise instead of Sunday, last week you'll probably see something like Almost half past eight in the evening of February 20th, 2005 for every post - which is ridiculous.
My SMF Mods:

Louis (CSpotkill)

My only concern with the Friendly Time mod in its current implementation is that I now realise the "last week" calculation is a little flawed. Well, it works - it just might not work the way people might expect it to. Because it uses PHP's date function, it thinks a week starts on Monday, when SMF's "First day of the week on the calendar" setting in every profile is probably set to Sunday.

Tip: If you want to make sure the relative time is correct, you can easily view the SMF default time format just by hovering your mouse over a relative time. (It will show up as a tooltip on any modern browser, like Firefox.)
My SMF Mods:

Anguz

#2
Hey! Congrats on your mod. I had thought it'd be nice to have the option to use something like this in some forums. Liked it a bit at Flickr.com, although I'm not really used to it and it's a bit different, too. Instead of dates, I think it says x minutes/days/weeks/months ago without being too specific, which helps keeping the string short.

Can this friendly format be an option from profile? I haven't tried it, so sorry for asking if it is, I wouldn't think it nice to impose this on all the members. BTW, the first day of the week in SMF can be chosen by you (Sunday/Monday).
Cristián Lávaque http://cristianlavaque.com

Louis (CSpotkill)

Thanks for the feedback! :D

You'd be surprised at how short, yet easy to understand, the dates are. I try to keep thing's "rough", not specific. So it says "Mid-March" instead of "10 pm on Tuesday, March 8th, 2005" - who really cares what day or time it was, if it's more than X away? Those types of things ...

The profile option is a good idea. It'd be quite easy to implement too. But at the same time, I haven't had any complaints on the forums I run about it, most people quite like it. However, I can understand if, for example, many of your forum's members don't understand English. Perhaps I should do a quick language check before I display the time in English automatically.

And I know you can pick the first day of the week in SMF (by default, and in people's profiles), that's why I said it was a problem if the week calculation automatically assumes that weeks start on Monday. I just don't know if it's a big enough deal to work out a way to adjust it based on the setting.
My SMF Mods:

Fizzy

That's a nice touch to the theme :)

Congratz
"Reality is merely an illusion, albeit a very persistent one." - A.E.


maufonseca

Wow, I have to install this one!

Louis (CSpotkill)

Thanks for the great comments :) I'm glad you all like it.

One plan I have is of making a whole series of "Friendly" mods to SMF, which are easy-to-install and improve some usability aspect for SMF. But then I realised that half of my mod ideas wouldn't sound right if they started with "Friendly". "Find-as-you-type Search" is better than "Friendly Search", eh? And "Friendly Creative Commons" doesn't sound right either. Oh well, I'll just keep the "Friendly" aspect in mind as I make the mods.
My SMF Mods:

friend

hi i installed the mod but my members didnt like it so i uninstalled it and deleted it but it still shows time as "quarter past nine" "last saturday" !! how do i change it back to the original? i dont understand as ive deleted and uninstalled the mod?

Louis (CSpotkill)

#8
What version of SMF are you using? Do you know what software your web host uses? I've never had that happen to me yet.

If you don't have any other mods installed (or don't mind re-installing them) the easiest way to fix this is to download a fresh smf install zip (like smf_1-0-2_install.zip), and re-upload the Sources/Subs.php file.

Otherwise, you'll have to manually edit Sources/Subs.php ...

Open Sources/Subs.php and select the following:

    // Strip slashes off the time format string.
    $str = $user_info['time_format'];

    if (setlocale(LC_TIME, @$txt['lang_locale']))
    {
      $str = ereg_replace('%a', ucwords(strftime('%a', $time)), $str);
      $str = ereg_replace('%A', ucwords(strftime('%A', $time)), $str);
      $str = ereg_replace('%b', ucwords(strftime('%b', $time)), $str);
      $str = ereg_replace('%B', ucwords(strftime('%B', $time)), $str);
    }
    else
    {
      // Do-it-yourself time localization.  Fun.
      $str = ereg_replace('%a', @$days_short[(int) strftime('%w', $time)], $str);
      $str = ereg_replace('%A', @$days[(int) strftime('%w', $time)], $str);
      $str = ereg_replace('%b', @$months_short[(int) strftime('%m', $time)], $str);
      $str = ereg_replace('%B', @$months[(int) strftime('%m', $time)], $str);
      $str = ereg_replace('%p', (strftime('%H', $time) < 12 ? 'am' : 'pm'), $str);
    }

    // Format any other characters..
    $before = '<span title="'.strftime($str, $time).'" style="cursor:default">';
    $after = '</span>';

    // Setup some variables
    $then = @getdate($time);
    $now = @getdate($nowtime);
    $then['week'] = date("W",$time);
    $now['week'] = date("W",$nowtime);
    $fourWeeksAgo = date("W", strtotime("-4 weeks", $nowtime));
    $WeeksAgo = date("W", $nowtime-$time);
   
    // Are we more than four weeks ago?
    if ($WeeksAgo > $fourWeeksAgo || $then['year'] != $now['year'])
    {
      // First let's see if it's for a previous year.
      if ($then['year'] != $now['year'])
      {
        $lastYear = date("Y", strtotime("-1 year", $nowtime));
         
        // If last month, write "early last month" or "last month", otherwise it's "Late October, last year" or "Mid-October, 2003".
        if ($then['mday'] < 10)
          return $before . (($then['mon'] == 12 && $now['mon'] == 1 && $then['year'] == $lastYear) ? 'Early last month' : 'Early ' . $then['month'] . (($then['year'] == $lastYear) ? ', last year' : ', ' . $then['year'])) . $after;
        if ($then['mday'] > 20)
          return $before . (($then['mon'] == 12 && $now['mon'] == 1 && $then['year'] == $lastYear) ? 'Late last month' : 'Late ' . $then['month'] . (($then['year'] == $lastYear) ? ', last year' : ', ' . $then['year'])) . $after;
        return $before . (($then['mon'] == 12 && $now['mon'] == 1 && $then['year'] == $lastYear) ? 'Last month' : 'Mid-' . $then['month'] . (($then['year'] == $lastYear) ? ', last year' : ', ' . $then['year'])) . $after;
      }
      // Next, compare month to see if it's a previous month.
      if ($then['mon'] != $now['mon'])
      {
        $lastMonth = date("n", strtotime("-1 month", $nowtime));
       
        // If last month, write "early last month" or "last month", otherwise it's "Late last October" or "Last October".
        if ($then['mday'] < 10)
          return $before . (($then['mon'] == $lastMonth) ? 'Early last month' : 'Early last ' . $then['month']) . $after;
        if ($then['mday'] > 20)
          return $before . (($then['mon'] == $lastMonth) ? 'Late last month' : 'Late last ' . $then['month']) . $after;
        return $before . (($then['mon'] == $lastMonth) ? 'Last month' : 'Last ' . $then['month']) . $after;
      }
    } // We're less than four weeks ago:
   
    // Setup more variables
    $yesterday = date("z", strtotime("-1 day", $nowtime));
   
    // Then compare the week. Are we this week or not?
    if ($then['week'] != $now['week'] && $then['yday'] < $yesterday)
    {
      $lastWeek = date("W", strtotime("-1 week", $nowtime));
      // If not this week then check to see if it's last week so we can say so, like: Tuesday, Last week
      if ($then['week'] == $lastWeek)
        return $before . $then['weekday'] . ', last week' . $after;
     
      $twoWeeksAgo = date("W", strtotime("-2 weeks", $nowtime));
      $threeWeeksAgo = date("W", strtotime("-3 weeks", $nowtime));
     
      // else ... Two weeks ago, Three weeks ago, or even Four weeks ago (all without day)
      return $before . (($then['week'] == $twoWeeksAgo) ? 'Two weeks ago' : (($then['week'] == $threeWeeksAgo) ? 'Three weeks ago' : 'Four weeks ago')) . $after;
    }

    // Finally, compare the day of the week to see if it's today or not.
    if ($then['yday'] != $now['yday'])
    {
      $timeOfDayArray = array( 0 => 'night', 1 => 'night', 2 => 'night',
        3 => 'night', 4 => 'night', 5 => 'morning', 6 => 'morning',
        7 => 'morning', 8 => 'morning', 9 => 'morning', 10 => 'morning',
        11 => 'morning', 12 => 'afternoon', 13 => 'afternoon',
        14 => 'afternoon', 15 => 'afternoon', 16 => 'afternoon',
        17 => 'afternoon', 18 => 'evening', 19 => 'evening',
        20 => 'evening', 21 => 'evening', 22 => 'night', 23 => 'night',
      );

      // List day name + time, like Tuesday morning, if not yesterday.
      if ($then['yday'] < $yesterday)
        return $before . $then['weekday'] . ' ' . $timeOfDayArray[$then['hours']] . $after;

      $hourOfYesterdayArray = array( 0 => 'midnight', 1 => '1 o&#39;clock',
        2 => '2 o&#39;clock', 3 => '3 o&#39;clock', 4 => '4 o&#39;clock',
        5 => '5 o&#39;clock', 6 => '6 o&#39;clock', 7 => '7 o&#39;clock',
        8 => '8 o&#39;clock', 9 => '9 o&#39;clock', 10 => '10 o&#39;clock',
        11 => '11 o&#39;clock', 12 => 'noon', 13 => '1 o&#39;clock',
        14 => '2 o&#39;clock', 15 => '3 o&#39;clock', 16 => '4 o&#39;clock',
        17 => '5 o&#39;clock', 18 => '6 o&#39;clock', 19 => '7 o&#39;clock',
        20 => '8 o&#39;clock', 21 => '9 o&#39;clock', 22 => '10 o&#39;clock',
        23 => '11 o&#39;clock',
      );
     
      // Replace day name with "Yesterday" - and make it "Last night" instead of "Yesterday night".
      return $before . (($timeOfDayArray[$then['hours']] == 'night') ? 'Last night ' : 'Yesterday ' . (($then['hours'] != 0 && $then['hours'] != 12) ? $timeOfDayArray[$then['hours']] . ' ' : '')) . 'at ' . $hourOfYesterdayArray[$then['hours']] . $after;
    }
   
    // It's today, so compare the time. First hours, then minutes, then seconds ...
    $hoursAgo = round(($nowtime-$time) / 3600);
    if ($hoursAgo >= 1)
    {
      // If it was posted three or less hours ago then say, "Three hours ago", "An hour ago" ...
      if ($hoursAgo <= 3)
        return $before . (($hoursAgo == 1) ? 'An hour ago' : (($hoursAgo == 2) ? 'Two hours ago' : 'Three hours ago')) . $after;
     
      // More than three hours ago, so let's reformat as "This morning at midnight" with some array magic.
      $timeOfTodayArray = array( 0 => 'This morning', 1 => 'This morning',
        2 => 'This morning', 3 => 'This morning', 4 => 'This morning',
        5 => 'This morning', 6 => 'This morning',   7 => 'This morning',
        8 => 'This morning', 9 => 'This morning', 10 => 'This morning',
        11 => 'This morning', 12 => 'This afternoon', 13 => 'This afternoon',
        14 => 'This afternoon', 15 => 'This afternoon', 16 => 'This afternoon',
        17 => 'This afternoon', 18 => 'This evening', 19 => 'This evening',
        20 => 'This evening', 21 => 'This evening', 22 => 'Tonight',
        23 => 'Tonight',
      );
     
      $hourOfTodayArray = array( 0 => 'midnight', 1 => '1 o&#39;clock',
        2 => '2 o&#39;clock', 3 => '3 o&#39;clock', 4 => '4 o&#39;clock',
        5 => '5 o&#39;clock', 6 => '6 o&#39;clock',   7 => '7 o&#39;clock',
        8 => '8 o&#39;clock', 9 => '9 o&#39;clock', 10 => '10 o&#39;clock',
        11 => '11 o&#39;clock', 12 => 'noon', 13 => '1 o&#39;clock',
        14 => '2 o&#39;clock', 15 => '3 o&#39;clock', 16 => '4 o&#39;clock',
        17 => '5 o&#39;clock', 18 => '6 o&#39;clock',   19 => '7 o&#39;clock',
        20 => '8 o&#39;clock', 21 => '9 o&#39;clock', 22 => '10 o&#39;clock',
        23 => '11 o&#39;clock',
      );
     
      return $before . (($then['hours'] != 0 && $then['hours'] != 12) ? $timeOfTodayArray[$then['hours']] : 'Today') . ' at ' . $hourOfTodayArray[$then['hours']] . $after;
    }
    // Next we'll check the minutes ...
    $minutesAgo = round(($nowtime-$time) / 60);
    if ($minutesAgo >= 1)
    {
      // A minute ago, two minutes ago, three minutes ago
      if ($minutesAgo <= 3)
        return $before . (($minutesAgo == 1) ? 'A minute ago' : (($minutesAgo == 2) ? 'Two minutes ago' : 'Three minutes ago')) . $after;
       
      // This is a little more complex, what we're doing is doubling
      // the minutes, then rounding to the nearest 10 and cutting it
      // in half. This way, we can round to the nearest 5. Isn't
      // it clever? I thought so too :p
     
      $roundedToFive = round($minutesAgo*2,-1) / 2;
     
      // five minutes ago, 10 minutes ago, 15 minutes ago,
      if ($roundedToFive <= 15)
      {
        if ($roundedToFive == 5)
          return $before . 'Five minutes ago' . $after;
        return $before . $roundedToFive . ' minutes ago' . $after;
      }
      // 20, 30, 40, 50 ... minutes ago.
      $roundedToTen = round($minutesAgo,-1);
      return $before . $roundedToTen . ' minutes ago' . $after;
    }
    $secondsAgo = $nowtime-$time;
    if ($secondsAgo < 30)
        return $before . 'Just now, seconds ago' . $after;
    return $before . '30 seconds ago' . $after;
  }
  // Not relative time? Then we must be formatting the current time ...

  // Split the time we're given into an array ...
  $timeArray = @getdate($time);

  // Use these to represend the minutes, before the hour phrase.
  $minutePhrases = array(
    0 => 'Around ',
    5 => 'A little after ',
    10 => 'Ten after ',
    15 => 'Quarter past ',
    20 => 'Twenty past ',
    25 => 'Almost half past ',
    30 => 'Half past ',
    35 => 'Almost twenty to ',
    40 => 'Twenty to ',
    45 => 'Quarter to ',
    50 => 'Ten to ',
    55 => 'Almost ',
    60 => 'Around ',
  );
   
  // This is a little more complex, what we're doing is doubling
  // the minutes, then rounding to the nearest 10 and cutting it
  // in half. This way, we can round to the nearest 5. Isn't
  // it clever? I thought so too :p
  $roundedMinutes = round($timeArray['minutes']*2,-1) / 2;
 
  $hourPhrases = array(
    0 => 'midnight on ',
    1 => 'one in the morning of ',
    2 => 'two in the morning of ',
    3 => 'three in the morning of ',
    4 => 'four in the morning of ',
    5 => 'five in the morning of ',
    6 => 'six in the morning of ',
    7 => 'seven in the morning of ',
    8 => 'eight in the morning of ',
    9 => 'nine in the morning of ',
    10 => 'ten in the morning of ',
    11 => 'eleven in the morning of ',
    12 => 'noon on ',
    13 => 'one in the afternoon of ',
    14 => 'two in the afternoon of ',
    15 => 'three in the afternoon of ',
    16 => 'four in the afternoon of ',
    17 => 'five in the afternoon of ',
    18 => 'six in the evening of ',
    19 => 'seven in the evening of ',
    20 => 'eight in the evening of ',
    21 => 'nine, on the night of ',
    22 => 'ten, on the night of ',
    23 => 'eleven, on the night of ',
  );
   
  // Next let's see if we have to adjust the hour or not ...
  // If we have to, then add an hour to the $time and get the new time array.
  $adjustedTime = ($roundedMinutes <= 30) ? $timeArray : @getdate(strtotime("+1 hour", $time));
   
  $mdayEnding = array(
    0 => 'th',
    1 => 'st',
    2 => 'nd',
    3 => 'rd',
  );
   
  // Okay, let's return the whole thing now ...
  return $minutePhrases[$roundedMinutes] . $hourPhrases[$adjustedTime['hours']] . $adjustedTime['month'] . ' ' . $adjustedTime['mday'] . (($adjustedTime['mday'] <= 3) ? $mdayEnding[$adjustedTime['mday']] : 'th') . ', ' . $adjustedTime['year'];


Replace what you selected above with the following code, by copying and pasting it:

$then = @getdate($time);
$now = @getdate($nowtime);

// Try to make something of a time format string...
if (strpos($user_info['time_format'], '%H') === false && strpos($user_info['time_format'], '%T') === false)
$today_fmt = '%I:%M:%S %p';
else
$today_fmt = '%H:%M:%S';

// Same day of the year, same year.... Today!
if ($then['yday'] == $now['yday'] && $then['year'] == $now['year'])
return $txt['smf10'] . strftime($today_fmt, $time);

// Day-of-year is one less and same year, or it's the first of the year and that's the last of the year...
if ($modSettings['todayMod'] == '2' && (($then['yday'] == $now['yday'] - 1 && $then['year'] == $now['year']) || ($now['yday'] == 0 && $then['year'] == $now['year'] - 1) && $then['mon'] == 12 && $then['mday'] == 31))
return $txt['smf10b'] . strftime($today_fmt, $time);
}

// Strip slashes off the time format string.
$str = $user_info['time_format'];

if (setlocale(LC_TIME, @$txt['lang_locale']))
{
$str = ereg_replace('%a', ucwords(strftime('%a', $time)), $str);
$str = ereg_replace('%A', ucwords(strftime('%A', $time)), $str);
$str = ereg_replace('%b', ucwords(strftime('%b', $time)), $str);
$str = ereg_replace('%B', ucwords(strftime('%B', $time)), $str);
}
else
{
// Do-it-yourself time localization.  Fun.
$str = ereg_replace('%a', @$days_short[(int) strftime('%w', $time)], $str);
$str = ereg_replace('%A', @$days[(int) strftime('%w', $time)], $str);
$str = ereg_replace('%b', @$months_short[(int) strftime('%m', $time)], $str);
$str = ereg_replace('%B', @$months[(int) strftime('%m', $time)], $str);
$str = ereg_replace('%p', (strftime('%H', $time) < 12 ? 'am' : 'pm'), $str);
}

// Format any other characters..
return strftime($str, $time);


Sorry it didn't work out for you. Please answer the questions I asked at the beginning of this post, to help make this mod better. Thanks for trying Friendly Time.
My SMF Mods:

Raffoz

beautiful mod...

i'm italian and wanted to translate it...

but i noticed it makes something strange... in my forum always apperas "last post 2 weeks ago"... instead in the forum where is the link of your mod... "last post" doesn't appear... why?
MacOsX (last)
SMF 2.0.15 and 2.1.2 (different forums)
Chrome (last) or Safari (last)

squeeze

Hey Man how i remove spam-me-not from SMF 1.0.5?

dtm.exe

Quote from: squeeze on June 23, 2005, 11:00:04 AM
Hey Man how i remove spam-me-not from SMF 1.0.5?

Please post this question in the appropriate thread...

-Dan The Man

squeeze

Hey man i see to reply to this thread, look at this url:

http://mods.simplemachines.org/index.php?mod=107

Note: Only tested with SMF 1.0.2 - The modification should work in previous versions, but the installer might not. If you get any problems, please reply with your SMF/Spam-me-not version numbers, and I'll try to fix the problems as soon as possible.

dtm.exe

Quote from: squeeze on June 23, 2005, 11:23:26 AM
Hey man i see to reply to this thread, look at this url:

http://mods.simplemachines.org/index.php?mod=107

Note: Only tested with SMF 1.0.2 - The modification should work in previous versions, but the installer might not. If you get any problems, please reply with your SMF/Spam-me-not version numbers, and I'll try to fix the problems as soon as possible.

OK, well continue this discussion in that topic, OK?

-Dan The Man

rhizome

Hi Louis

This is a very cool mod, and something similar I recently asked for, but didn't see your mod before

The time is certainly now more friendly.

I was wondering though, if it possible to alter things, and make it even more simpler.

Sorry, I know it sounds presumptious asking for a way of changing things, but thought you maybe interested anyway to make it even more friendlier  :)

The thinking is that anything relative to the date of viewing, shoud be kept simple as possible


So here goes - instead of displaying:

yesterday afternoon at 2 o'clock -> yesterday, 2pm

tuesday night -> 2 days ago

early last month -> last month

early last March -> March, 2005

Maybe the mod could be developed further, so it gives various options/formats how the dates could be displayed.

BTW, I haven't installed it yet, is there a way of disabling the display of how long it took to compose the message?

best regards
rhizome

thaJack

Where would I go to change the text?  for instance, I want to change it from saying "Three weeks ago" to "three weeks ago"

Just the casing on some of it... so I don't see "Last post Three weeks ago".  I would rather see "Last post three weeks ago"

dtm.exe

Quote from: thaJack on September 07, 2005, 10:27:58 AM
Where would I go to change the text?  for instance, I want to change it from saying "Three weeks ago" to "three weeks ago"

Just the casing on some of it... so I don't see "Last post Three weeks ago".  I would rather see "Last post three weeks ago"

Search for that text in Modifications.[language].php.

thaJack

Quote from: OIDanTheManIO on September 07, 2005, 11:09:24 AM
Search for that text in Modifications.[language].php.

Wasn't in there.

ANARCH¥

 // else ... Two weeks ago, Three weeks ago, or even Four weeks ago (all without day)
      return $before . (($then['week'] == $twoWeeksAgo) ? 'Two weeks ago' : (($then['week'] == $threeWeeksAgo) ? 'Three weeks ago' : 'Four weeks ago')) . $after;
    }


this mod just made a change in Subs.php, so just edit the file and you will find it ... :P

carlatf

hi,
I'm translating this to Spanish  but I have some problems, for example:
" // 20, 30, 40, 50 ... minutes ago.
      $roundedToTen = round($minutesAgo,-1);
      return $before . $roundedToTen . ' minutes ago' . $after;"

in Spanish is not "X minutes ago" = "Hace X minutos"
how do I reverse the phrase correctly?. I did and I got a parse error, I supose I put the '' in the wrong place.
Many thanks.
Carla

Advertisement: