September 22, 2010

How to format the time span between now and the date specified in a "Facebook way"

Recently I was looking for some method to format the time span between now and the date specified in a "Facebook way". There are some, but none was completely what I was looking for. So I have decided to create mine. Moreover, it's not that complicated:
package {

import mx.formatters.DateFormatter;
import mx.utils.StringUtil;

public class DateUtil {

public static const SECOND_IN_MILLISECONDS : int = 1000;

public static const FEW_SECONDS : int = 5;

public static const MINUTE_IN_SECONDS : int = 60;

public static const HOUR_IN_SECONDS : int = MINUTE_IN_SECONDS * 60;

private static const X_SECONDS_AGO : String = "{0} seconds ago";

private static const X_MINUTES_AGO : String = "{0} minutes ago";

private static const X_HOURS_AGO : String = "{0} hours ago";

private static const IN_X_SECONDS : String = "In {0} seconds";

private static const IN_X_MINUTES : String = "In {0} minutes";

private static const IN_X_HOURS : String = "In {0} hours";

private static const YESTERDAY_TOMORROW_PATTERN : String = "at L:NNA";

private static const THIS_WEEK_PATTERN : String = "EEEE at L:NNA";

private static const THIS_YEAR_PATTERN : String = "MMMM D at L:NNA";

private static const ANOTHER_YEAR_PATTERN : String = "MMMM D, YYYY at L:NNA";

/**
         * Format the time span between now and the date specified in a "Facebook way".
         *
         * Examples:
         *
         * May 18, 2011 at 5:11AM
         * December 25 at 8:43PM
         * Friday at 3:53PM
         * Tomorrow at 10:44AM
         * In 10 hours
         * In about an hour
         * In 25 minutes
         * In about a minute
         * In 17 seconds
         * In a few seconds
         * A few seconds ago
         * 31 seconds ago
         * About a minute ago
         * 47 minutes ago
         * About an hour ago
         * 4 hours ago
         * Yesterday at 6:25PM
         * Monday at 12:30AM
         * September 11 at 7:11AM
         * September 10, 2009 at 12:23PM
         */
public static function getTimeSpan(date : Date) : String {
var result : String;
var now : Date = new Date();
var dateFormatter : DateFormatter = new DateFormatter();
var range : Number = (now.time - date.time) / SECOND_IN_MILLISECONDS;

var nextYearStart : Date = new Date(now.fullYear + 1, 0, 1);
var nextWeekStart : Date = new Date(now.fullYear, now.month, now.date + (7 - now.day));
var tomorrowStart : Date = new Date(now.fullYear, now.month, now.date + 1);
var theDayAfterTomorrowStart : Date = new Date(now.fullYear, now.month, now.date + 2);
var todayStart : Date = new Date(now.fullYear, now.month, now.date);
var yesterdayStart : Date = new Date(now.fullYear, now.month, now.date - 1);
var thisWeekStart : Date = new Date(now.fullYear, now.month, now.date - now.day);
var thisYearStart : Date = new Date(now.fullYear, 0, 1);

var nextYearRange : Number = (now.time - nextYearStart.time) / SECOND_IN_MILLISECONDS;
var nextWeekRange : Number = (now.time - nextWeekStart.time) / SECOND_IN_MILLISECONDS;
var theDayAfterTomorrowRange : Number = (now.time - theDayAfterTomorrowStart.time) / SECOND_IN_MILLISECONDS;
var tomorrowRange : Number = (now.time - tomorrowStart.time) / SECOND_IN_MILLISECONDS;
var todayRange : Number = (now.time - todayStart.time) / SECOND_IN_MILLISECONDS;
var yesterdayRange : Number = (now.time - yesterdayStart.time) / SECOND_IN_MILLISECONDS;
var thisWeekRange : Number = (now.time - thisWeekStart.time) / SECOND_IN_MILLISECONDS;
var thisYearRange : Number = (now.time - thisYearStart.time) / SECOND_IN_MILLISECONDS;

if (range >= 0) {
if (range < FEW_SECONDS) {
result = "A few seconds ago";
} else if (range < MINUTE_IN_SECONDS) {
result = StringUtil.substitute(X_SECONDS_AGO, Math.floor(range));
} else if (range < MINUTE_IN_SECONDS * 2) {
result = "About a minute ago";
} else if (range < HOUR_IN_SECONDS) {
result = StringUtil.substitute(X_MINUTES_AGO, Math.floor(range / MINUTE_IN_SECONDS));
} else if (range < HOUR_IN_SECONDS * 2) {
result = "About an hour ago";
} else if (range < todayRange) {
result = StringUtil.substitute(X_HOURS_AGO, Math.floor(range / HOUR_IN_SECONDS));
} else if (range < yesterdayRange) {
dateFormatter.formatString = YESTERDAY_TOMORROW_PATTERN;
result = "Yesterday " + dateFormatter.format(date);
} else if (range < thisWeekRange) {
dateFormatter.formatString = THIS_WEEK_PATTERN;
result = dateFormatter.format(date);
} else if (range < thisYearRange) {
dateFormatter.formatString = THIS_YEAR_PATTERN;
result = dateFormatter.format(date);
} else {
dateFormatter.formatString = ANOTHER_YEAR_PATTERN;
result = dateFormatter.format(date);
}
} else {
if (range > -FEW_SECONDS) {
result = "In a few seconds";
} else if (range > -MINUTE_IN_SECONDS) {
result = StringUtil.substitute(IN_X_SECONDS, Math.floor(-range));
} else if (range > -MINUTE_IN_SECONDS * 2) {
result = "In about a minute";
} else if (range > -HOUR_IN_SECONDS) {
result = StringUtil.substitute(IN_X_MINUTES, Math.floor(-range / MINUTE_IN_SECONDS));
} else if (range > -HOUR_IN_SECONDS * 2) {
result = "In about an hour";
} else if (range > tomorrowRange) {
result = StringUtil.substitute(IN_X_HOURS, Math.floor(-range / HOUR_IN_SECONDS));
} else if (range > theDayAfterTomorrowRange) {
dateFormatter.formatString = YESTERDAY_TOMORROW_PATTERN;
result = "Tomorrow " + dateFormatter.format(date);
} else if (range > nextWeekRange) {
dateFormatter.formatString = THIS_WEEK_PATTERN;
result = dateFormatter.format(date);
} else if (range > nextYearRange) {
dateFormatter.formatString = THIS_YEAR_PATTERN;
result = dateFormatter.format(date);
} else {
dateFormatter.formatString = ANOTHER_YEAR_PATTERN;
result = dateFormatter.format(date);
}
}

return result;
}
}
}

1 comments:

Anonymous said...

public static const MINUTE_IN_SECONDS : int = 60;

shouldn't be seconds in minute ? :)