views:

220

answers:

3

Is there a free library or class for formatting a date in a pretty way such as "5 minutes ago" or "yesterday"?

I'd be satisfied with the same code in another language that I could port to Actionscript (like Java or C#)

+2  A: 

Hi Mims, would this help? Should be very easy to port to AS3.

/*
 * JavaScript Pretty Date
 * Copyright (c) 2008 John Resig (jquery.com)
 * Licensed under the MIT license.
 */

// Takes an ISO time and returns a string representing how
// long ago the date represents.
function prettyDate(time){
    var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," ")),
     diff = (((new Date()).getTime() - date.getTime()) / 1000),
     day_diff = Math.floor(diff / 86400);

    if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 )
     return;

    return day_diff == 0 && (
      diff < 60 && "just now" ||
      diff < 120 && "1 minute ago" ||
      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
      diff < 7200 && "1 hour ago" ||
      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
     day_diff == 1 && "Yesterday" ||
     day_diff < 7 && day_diff + " days ago" ||
     day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
}

// If jQuery is included in the page, adds a jQuery plugin to handle it as well
if ( typeof jQuery != "undefined" )
    jQuery.fn.prettyDate = function(){
     return this.each(function(){
      var date = prettyDate(this.title);
      if ( date )
       jQuery(this).text( date );
     });
    };
Joel Hooks
+1  A: 

I'm using this Relative Time code for a Twitter widget I'm working on. It's PHP, but nothing feature-specific so a port should be pretty easy.

Hugh Guiney
Also a nice sample. thanks!
Mims H. Wright
A: 

I ended up writing my own.

/** 
 * Takes a Date object and returns a string in the format
 * "X UNITS ago" where X is a number and UNITS is a unit of
 * time. Also has some other strings like "yesterday".
 * 
 * @author Mims Wright (with thanks to John Resig)
 * 
 * @param date The date to convert to a past string.
 * @param now Optional time to compare against. Default will be the present.
 */ 
public function getTimeElapsedString(date:Date, now:Date = null):String {

 const SEC_PER_MINUTE:int = 60;
 const SEC_PER_HOUR:int = SEC_PER_MINUTE * 60;
 const SEC_PER_DAY:int = SEC_PER_HOUR * 24;
 const SEC_PER_WEEK:int = SEC_PER_DAY * 7;
 const SEC_PER_MONTH:int = SEC_PER_DAY * 30;
 const SEC_PER_YEAR:int = SEC_PER_MONTH * 12; 

 // if now isn't defined, make it a new Date object (the present)
 if (!now) { now = new Date(); }

 // don't use secondsElapsed here because the values are 
 // huge so they use uints and are never negative
 if (now.time < date.time) { return "in the future"; }

 // get the difference in seconds between the two values. 
 var secondsElapsed:uint = Math.floor((now.time - date.time) / 1000);


 // seconds
 if (secondsElapsed < SEC_PER_MINUTE) { return "just now"; }

 // minutes
 if (secondsElapsed < SEC_PER_HOUR) { 
  var minutes:int = int(secondsElapsed / SEC_PER_MINUTE);
  return formatAgoString(minutes, "minute");
 }

 // hours
 if (secondsElapsed < SEC_PER_DAY) { 
  var hours:int = int(secondsElapsed / SEC_PER_HOUR);
  return formatAgoString(hours, "hour");
 }

 // days
 if (secondsElapsed < SEC_PER_WEEK) { 
  var days:int = int(secondsElapsed / SEC_PER_DAY);
  if (days == 1) { return "yesterday"; }

  return formatAgoString(days, "day");
 }

 // weeks
 if (secondsElapsed < SEC_PER_MONTH) { 
  var weeks:int = int(secondsElapsed / SEC_PER_WEEK);
  return formatAgoString(weeks, "week");
 }

 // months
 if (secondsElapsed < SEC_PER_YEAR) { 
  var months:int = int(secondsElapsed / SEC_PER_MONTH);
  return formatAgoString(months, "month");
 }

 // years
 return "more than a year ago";

 // Returns a string in the format "count unit(s) ago"
 function formatAgoString(count:int, unit:String):String {
  return count + " " + unit + (count > 1 ? "s" : "") + " ago";
 }
}
Mims H. Wright