ASP.Net MVC Friendly Dates

Welcome to the colony… Well, over the weekend I caught a terrible bug and had to miss work today. While I’m laying here in bed, I thought I might post something (yes, I’m that bored).

While poking around my old CMS, I thought about how I went about using friendly dates on all the forums and blog posts. Usually I’d use an external function, but with MVC, you can extend the HtmlHelper class directly and apply the new function right in the view.

I.E. Instead of…

 <%= Html.Encode(item.LastModified)%>

Use…

 <%= Html.FriendlyDate(item.LastModified)%>

The premise is fairly simple and you can probably implement something more efficient than this. But considering I feel like my head is in a vise right now, this would have to do.

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;

// Important to use the default Mvc.Html namespace as that's what we're extending
namespace System.Web.Mvc.Html
{
	public static class HtmlExtensions
	{
		public static string FriendlyDate(this HtmlHelper helper, Object ddt)
		{
			// Get all the variables set
			DateTime dt = (DateTime)ddt;
			DateTime now = DateTime.Now;
			StringBuilder sb = new StringBuilder();
			TimeSpan elapsed;

			int days = 0;
			int hours = 0;
			int minutes = 0;
			int years = 0;

			// If the given date is *before* now
			if (now > dt)
				elapsed = now.Subtract(dt);
			// If the given date is *after* now
			else
				elapsed = dt.Subtract(now);

			// Leap years are always fun... 
			// I don't care too much about accuracy after the current year
			if (DateTime.IsLeapYear(dt.Year))
				years = (int)(elapsed.Days / 366);
			else
				years = (int)(elapsed.Days / 365);

			days = (int)elapsed.TotalDays;
			hours = (int)elapsed.TotalHours;
			minutes = (int)elapsed.TotalMinutes;

			// There aren't any hours days or years yet
			if (years <= 0 && days <= 0 && hours <= 0)
			{
				if (minutes > 0)
				{
					sb.Append(minutes.ToString("0") + " minute");

					if (minutes > 1)
						sb.Append("s");
				}
			}
			else
			{
				// If we have years, then days and hours don't really mean much
				if (years > 0)
				{
					if (years < 10)
					{
						sb.Append(years.ToString("0") + " year");
						if (years > 1)
							sb.Append("s");
					}
					// ... Hey, ASP lasted quite a while. You just never know.
					else if (years > 10 && years < 30)
					{
						int dec = years / 10;
						sb.Append(dec + " decade");
						if (dec > 1)
							sb.Append("s");
					}
					else
					{
						sb.Append("A very long time");
					}
				}
				else
				{
					// We have days and hours
					if (days > 0)
					{
						sb.Append(days.ToString("0") + " day");
						if (days > 1)
							sb.Append("s");
					}
					if (hours > 0)
					{
						sb.Append(" " + hours.ToString("0") + " hour");
						if (hours > 1)
							sb.Append("s");
					}
				}
			}

			if (now > dt)
				// Past time
				sb.Append(" ago");
			else
				// Future time
				sb.Append(" from now");

			return sb.ToString();
		}
	}
}
About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s