Note:  I’m having some problems formatting the code samples inserted into this post.  I write my posts with LiveWriter.  The first few samples are inserted with a pluggin, VSPaste which always worked great for me.  But today the line breaks keep getting removed.  For the larger sample below, I tried to use another pluggin called Code Snippet.  It kept the line breaks but now my indentations are removed! What a pain.  Not sure if the problem is LiveWriter or the addins.  I’ll update this when I figure it out.  Anyway…

 

Yesterday I wrote my first extension method and I thought it would make for a good post.  Ironically, yesterday ScottGu posted an extension method sample on his blog.  Are we thinking alike?  Wishful thinking by me, I guess!  Extension methods are one of the cool features you get with .Net 3.0.  You can use them to add functionality to an existing class without extending the class itself, even if the class is sealed.

Before I show my real extension method, here’s a simple example for fun.  Extension methods are pretty easy to create.  This method that returns a bool if a date is my birthday:

 public static bool IsMyBirthday(this DateTime date) { if (date.Month == 9 && date.Day == 21) return true; return false; }

The unusual part is  (this DateTime date).  This parameter is the part that hooks this extension method with the Object, in this case a DateTime.  And it acts like a regular parameter because inside the method I can refer to date to get the value.

It gets called as follows:

 DateTime myDate; if (myDate.IsMyBirthday()) return true;

or even:
 if (DateTime.Now.IsMyBirthday()) return true;

The extension method automatically attaches itself to instances of DateTime!  Of course, you have to include a reference to the namespace where the method lives.

OK, how about some real code.  My TimeAgo extension method extends DateTime and returns a string that represents the DateTime compared to Now as "5 minutes ago" or "2 weeks ago", etc.  You could do a lot more with this method.  I’m not getting too carried away with the logic for what is "yesterday" or "last month" and I am not considering time zone differences.  I’m keeping it simple, hopefully you get the idea.  Here is the code and also a test console app:

namespace Utilities
{
 public static class DateExtension
 {
 public static string TimeAgo(this DateTime date)
 {
 TimeSpan timeSince = DateTime.Now.Subtract(date);
 
 if (timeSince.TotalMilliseconds < 1)
 return "not yet";
 
 if (timeSince.TotalMinutes < 1)
 return "just now";
 if (timeSince.TotalMinutes < 2)
 return "1 minute ago";
 if (timeSince.TotalMinutes < 60)
 return string.Format("{0} minutes ago", timeSince.Minutes);
 if (timeSince.TotalMinutes < 120)
 return "1 hour ago";
 if (timeSince.TotalHours < 24)
 return string.Format("{0} hours ago", timeSince.Hours);
 if (timeSince.TotalDays == 1)
 return "yesterday";
 if (timeSince.TotalDays < 7)
 return string.Format("{0} days ago", timeSince.Days);
 if (timeSince.TotalDays < 14)
 return "last week";
 if (timeSince.TotalDays < 21)
 return "2 weeks ago";
 if (timeSince.TotalDays < 28)
 return "3 weeks ago";
 if (timeSince.TotalDays < 60)
 return "last month";
 if (timeSince.TotalDays < 365)
 return string.Format("{0} months ago", Math.Round(timeSince.TotalDays / 30));
 if (timeSince.TotalDays < 730)
 return "last year";
 //last but not least...
 return string.Format("{0} years ago", Math.Round(timeSince.TotalDays / 365));
 }
 }
 class Program
 {
 static void Main(string[] args)
 {
 DateTime date;
 
 date = DateTime.Now.AddSeconds(1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddSeconds(-5);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddMinutes(-1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddMinutes(-5);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddMinutes(-59);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddHours(-1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddHours(-2);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddHours(-23);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddDays(-1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddDays(-2);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddDays(-7);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddDays(-14);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddDays(-21);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddMonths(-1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddMonths(-11);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddYears(-1);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 date = DateTime.Now.AddYears(-2);
 Console.WriteLine(date.ToLongDateString() + " Time ago: " + date.TimeAgo());
 
 Console.Read();
 
 }
 }
 
}

 

 

One thought on “Extension Method for DateTime: TimeAgo()

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>