Question

Let's say I've got two strings in JavaScript:

var date1 = '2008-10-03T20:24Z'
var date2 = '2008-10-04T12:24Z'

How would I come to a result like so:

'4 weeks ago'

or

'in about 15 minutes'

(should support past and future).

There are solutions out there for the past diffs, but I've yet to find one with support for future time diffs as well.

These are the solutions I tried:

John Resig's Pretty Date and Zach Leatherman's modification

Bonus points for a jQuery solution.

Was it helpful?

Solution

Looking at the solutions you linked... it is actually as simple as my frivolous comment!

Here's a version of the Zach Leatherman code that prepends "In " for future dates for you. As you can see, the changes are very minor.

  function humane_date(date_str){
      var time_formats = [
          [60, 'Just Now'],
          [90, '1 Minute'], // 60*1.5
          [3600, 'Minutes', 60], // 60*60, 60
          [5400, '1 Hour'], // 60*60*1.5
          [86400, 'Hours', 3600], // 60*60*24, 60*60
          [129600, '1 Day'], // 60*60*24*1.5
          [604800, 'Days', 86400], // 60*60*24*7, 60*60*24
          [907200, '1 Week'], // 60*60*24*7*1.5
          [2628000, 'Weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
          [3942000, '1 Month'], // 60*60*24*(365/12)*1.5
          [31536000, 'Months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
          [47304000, '1 Year'], // 60*60*24*365*1.5
          [3153600000, 'Years', 31536000], // 60*60*24*365*100, 60*60*24*365
          [4730400000, '1 Century'], // 60*60*24*365*100*1.5
      ];

      var time = ('' + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),
          dt = new Date,
          seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
          token = ' Ago',
          prepend = '',
          i = 0,
          format;

      if (seconds < 0) {
          seconds = Math.abs(seconds);
          token = '';
          prepend = 'In ';
      }

      while (format = time_formats[i++]) {
          if (seconds < format[0]) {
              if (format.length == 2) {
                  return (i>1?prepend:'') + format[1] + (i > 1 ? token : ''); // Conditional so we don't return Just Now Ago
              } else {
                  return prepend + Math.round(seconds / format[2]) + ' ' + format[1] + (i > 1 ? token : '');
              }
          }
      }

      // overflow for centuries
      if(seconds > 4730400000)
          return Math.round(seconds / 4730400000) + ' Centuries' + token;

      return date_str;
  };

OTHER TIPS

Heh - I actually wrote a function to do this exact thing yesterday (and it's not on this computer so I'll just have to try to remember it)

I extended the Date prototype class, but this could quite easily just be put into a regular function.

Date.prototype.toRelativeTime = function(otherTime) {
    // if no parameter is passed, use the current date.
    if (otherTime == undefined) otherTime = new Date();

    var diff = Math.abs(this.getTime() - otherTime.getTime()) / 1000;

    var MIN = 60,        // some "constants" just 
        HOUR = 3600,     // for legibility
        DAY = 86400
    ;
    var out, temp;
    if (diff < MIN) {
        out = "Less than a minute";

    } else if (diff < 15 * MIN) {
        // less than fifteen minutes, show how many minutes
        temp = Math.round(diff / MIN);
        out = temp + " minute" + (temp == 1 ? "" : "s");
        // eg: 12 minutes
    } else if (diff < HOUR) {
        // less than an hour, round down to the nearest 5 minutes
        out = (Math.floor(diff / (5 * MIN)) * 5) + " minutes";
    } else if (diff < DAY) {
        // less than a day, just show hours
        temp = Math.round(diff / HOUR);
        out = temp + " hour" + (temp == 1 ? "" : "s");
    } else if (diff < 30 * DAY) {
        // show how many days ago
        temp = Math.round(diff / DAY);
        out = temp + " day" + (temp == 1 ? "" : "s");
    } else if (diff < 90 * DAY) {
        // more than 30 days, but less than 3 months, show the day and month
        return this.getDate() + " " + this.getShortMonth();  // see below
    } else {
        // more than three months difference, better show the year too
        return this.getDate() + " " + this.getShortMonth() + " " + this.getFullYear();
    }
    return out + (this.getTime() > otherTime.getTime() ? " from now" : " ago");

};

Date.prototype.getShortMonth = function() {
    return ["Jan", "Feb", "Mar",
            "Apr", "May", "Jun",
            "Jul", "Aug", "Sep",
            "Oct", "Nov", "Dec"][this.getMonth()];
};

// sample usage:
var x = new Date(2008, 9, 4, 17, 0, 0);
alert(x.toRelativeTime());    // 9 minutes from now

x = new Date(2008, 9, 4, 16, 45, 0, 0);
alert(x.toRelativeTime());    // 6 minutes ago

x = new Date(2008, 11, 1);    // 1 Dec

x = new Date(2009, 11, 1);    // 1 Dec 2009
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top