Archive for the 'Communication' Category

Fuzzy Time

Recently I discovered a need (read: desire that was relatively easily fulfilled, thus necessary) for a web app to have “fuzzy time” display capabilities.  You’ve got the ironclad, all-superior, well-known, never-fail Unix timestamp (e.g. 1126935037).  Backbone of a LOT software (and for good reason), but useless for display.  You’ve got the MySQL datetime, which is really nifty, but even for seasoned developers, can be a bit harsh on the eyes.  PHP is the winner by far.  With it’s function called date(), you can print strings like “Monday, November 17th, 2008 at 10:21am” which is much nicer.  Isn’t abstraction wonderful?

Let’s unpack this.  In each instance you’re moving away from a single, absolute integer, to an easier-on-the-eyes formatted string.  But why stop there?  That’s where “fuzzy time” functions come into play.  They take a given time value (timestamp, datetime, or something to that effect) and, with some very simple logic… lay it out in a much easier-to-swallow way, such as “today at 8:16am,” “yesterday around 1:30pm,” and “about two weeks ago.”  A buddy of mine used to have a fuzzy time widget for his (Fedora) desktop that ran the gambit, abstracting time as specifically as “early morning” to as generally as “early winter.”  Perhaps that’s going too far, perhaps not.  You be the judge - I thought it was pretty funny.

Back to the topic at hand.  I’ve always admired Facebook’s use of fuzzy time for status updates.

At certain times of day and night (and certain levels of non-sobriety) your users can’t even parse some of the nicest date() output.  So, I went ahead and wrote a very simple PHP function to take things just one level higher up the ole’ abstraction ladder. (Note that line 2 only existed in my example script to save me typing.)

function fuzzy_time( $time ) {
  echo "\"$time\" is: ";
  if ( ( $time = strtotime( $time ) ) == false ) {
    return 'an unknown time';
  }
  define( 'NOW',        time() );
  define( 'ONE_MINUTE', 60 );
  define( 'ONE_HOUR',   3600 );
  define( 'ONE_DAY',    86400 );
  define( 'ONE_WEEK',   ONE_DAY*7 );
  define( 'ONE_MONTH',  ONE_WEEK*4 );
  define( 'ONE_YEAR',   ONE_MONTH*12 );
 
  // sod = start of day :)
  $sod = mktime( 0, 0, 0, date( 'm', $time ), date( 'd', $time ), date( 'Y', $time ) );
  $sod_now = mktime( 0, 0, 0, date( 'm', NOW ), date( 'd', NOW ), date( 'Y', NOW ) );
 
  // used to convert numbers to strings
  $convert = array( 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7 => 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten', 11 => 'eleven' );
 
  // today
  if ( $sod_now == $sod ) {
    if ( $time > NOW-(ONE_MINUTE*3) ) {
      return 'just a moment ago';
    } else if ( $time > NOW-(ONE_MINUTE*7) ) {
      return 'a few minutes ago';
    } else if ( $time > NOW-(ONE_HOUR) ) {
      return 'less than an hour ago';
    }
    return 'today at ' . date( 'g:ia', $time );
  }
 
  // yesterday
  if ( ($sod_now-$sod) < = ONE_DAY ) {
    if ( date( 'i', $time ) > (ONE_MINUTE+30) ) {
      $time += ONE_HOUR/2;
    }
    return 'yesterday around ' . date( 'ga', $time );
  }
 
  // within the last 5 days
  if ( ($sod_now-$sod) < = (ONE_DAY*5) ) {
    $str = date( 'l', $time );
    $hour = date( 'G', $time );
    if ( $hour < 12 ) {
      $str .= ' morning';
    } else if ( $hour < 17 ) {
      $str .= ' afternoon';
    } else if ( $hour < 20 ) {
      $str .= ' evening';
    } else {
      $str .= ' night';
    }
    return $str;
  }
 
  // number of weeks (between 1 and 3)...
  if ( ($sod_now-$sod) < (ONE_WEEK*3.5) ) {
    if ( ($sod_now-$sod) < (ONE_WEEK*1.5) ) {
      return 'about a week ago';
    } else if ( ($sod_now-$sod) < (ONE_DAY*2.5) ) {
      return 'about two weeks ago';
    } else {
      return 'about three weeks ago';
    }
  }
 
  // number of months (between 1 and 11)...
  if ( ($sod_now-$sod) < (ONE_MONTH*11.5) ) {
    for ( $i = (ONE_WEEK*3.5), $m=0; $i < ONE_YEAR; $i += ONE_MONTH, $m++ ) {
      if ( ($sod_now-$sod) <= $i ) {
        return 'about ' . $convert[$m] . ' month' . (($m>1)?'s':'') . ' ago';
      }
    }
  }
 
  // number of years...
  for ( $i = (ONE_MONTH*11.5), $y=0; $i < (ONE_YEAR*10); $i += ONE_YEAR, $y++ ) {
    if ( ($sod_now-$sod) <= $i ) {
      return 'about ' . $convert[$y] . ' year' . (($y>1)?'s':'') . ' ago';
    }
  }
 
  // more than ten years...
  return 'more than ten years ago';
}

The original base-function I used was one that I found on PHPClasses by a fellow named Andrew Collington.  The code was in a class method for getting fuzzy file times.  I took that code, broke it out into a function, and massaged the heck out of it.  The function takes as it’s first parameter any value accepted by the PHP function  strtotime().  I chose that because of it’s impressive flexibility.  The function I ended up with only goes back to a ten-year period.  I figure, if I ever write anything that has records older than that, I can update it pretty easily.  Here’s sample output for all of the different intervals the function currently supports:


"now" is: just a moment ago
"-5 minutes" is: a few minutes ago
"-30 minutes" is: less than an hour ago
"-24 hours" is: yesterday around 10am
"-48 hours" is: Saturday morning
"-90 hours" is: Thursday afternoon
"-1 week" is: about a week ago
"-2 weeks" is: about three weeks ago
"-3 weeks" is: about three weeks ago
"-4 weeks" is: about one month ago
"-5 weeks" is: about one month ago
"-3 months" is: about three months ago
"-9 months" is: about nine months ago
"-13 months" is: about one year ago
"-76 months" is: about six years ago
"-9 years" is: about nine years ago
"-26 years" is: more than ten years ago

I was suprised at how much character and youth it gave the site.  Thanks Andrew and Facebook!

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

November 17 2008 | Communication and Development | No Comments »

Estimates? We don’t need no stinkin’ estimates!

ETAs on projects are among the very most necessary evils of software development. Why are they necessary? For a slew of reasons. Think about it - you don’t hand your car to a mechanic without asking him when he’ll be done fixing it. You wouldn’t pay a plumber to renovate your bathroom without finding out exactly how many days or weeks worth of mornings you’d have to walk next door to take your showers. In the same light, we cannot, as software developers, expect our overlords to agree to sending us nice pretty paychecks every Friday without any [reasonable] expectation of when we will deliver them their product.

So why are estimates evil? Well, we don’t have to discuss this one in great depth. Come on, they stink! Right? Think about it, you’ve got a large project ahead of you. One that involves multiple languages and protocols, different APIs, synchronization across processes and maybe even machines, mutual exclusion, exception handling, and/or whatever the case may be. And you’re supposed to [accurately, and with a straight face] tell the guy standing in front of you - who has NO idea what this project entails - when you’ll be done. Yeah… estimates are can be rough. Especially if it’s a project that’s relatively novel.

In the past, I struggled trying to get past the barriers to be able to honestly give relatively accurate predictions on software delivery times. But in a stroke of creativity (I don’t get these often, so it’s always nice when it does happen) I stumbled across the perfect analogy.

Picture yourself in Los Angeles. In a vehicle. Now, in twenty seconds or less, I want you to try to estimate how long it would take you, from there, to drive cross country to New York City. Got it? Of course you don’t. It’s difficult enough to even know where to start, unless you’ve actually done this kind of thing before. You can go on Google Maps, and it’ll estimate for you (1 day and 17 hours if you’re feeling a bit too lazy to follow the link). But will it really take this long? Can Google account for traffic jams? Accidents? Bad weather? Police? Detours? Potty breaks? Food breaks? Mechanical problems? Refueling? Sleeping?

Of course not. As much as I’m a Google fan, it’s not that good [yet].

I’ve found this analogy to be strikingly apropos. The perfect way to explain to your manager why exactly it is so difficult giving software delivery estimates. But it doesn’t help anyone who still actually needs to learn how to estimate projects with any degree of accuracy. You can read the Five-Minute-Task Time Estimate Worksheet. This is a good lesson for anyone new to the game - and hilarious for anyone who isn’t.

So, with all I’ve written thus far, you may by now be expecting some revolutionary, well presented, possibly alliterative, three step guide to producing accurate estimates on software projects. Well, here it is - get off your duff and start working. There is nothing you can be taught in this regard, in my experience. The intuition one may seem to have regarding project estimates has only been earned through much development. Many iterations of seeing projects (however large or small, personal or corporate) go from conceptualization to implementation.

Sorry to leave you high and dry, but experience is, after all, the best teacher.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

August 08 2008 | Communication and Development | No Comments »