Displaying time in relative format

Digg it! del.icio.us  |  kick it on DotNetKicks.com  |  Stay updated with rss  |  Add to Google


Many websites specially forum sites display time relative to the current time as “3 Hours 25 Minutes ago”, “30 Seconds ago” etc. In this post I will show a method using which we can convert datetime into descriptive relative time string.

The method takes 2 parameters 1. the time to process, 2. the time to which the output will be relative. Usually it is DateTime.UtcNow. There is also an overload which only takes the time to process where the second parameter defaults to DateTime.UtcNow. Let us see some sample output of this function.

Sample output

Output The date
29 August 2007 8/29/2007 4:28:02 AM
15 April (4 Months Ago) 4/15/2008 4:28:02
AM
16 August (12 Days Ago) 8/16/2008 4:28:02 AM
4 Hours 48 Minutes

Ago

8/27/2008 11:40:02 PM
43 Minutes 12 Seconds Ago 8/28/2008 3:44:50 AM
34

Seconds Ago

8/28/2008 4:27:27 AM
34 Seconds To go 8/28/2008 4:28:37 AM
43

Minutes 12 Seconds To go

8/28/2008 5:11:14 AM
4 Hours 48 Minutes To go 8/28/2008 9:16:02

AM

9 September (12 Days To go) 9/9/2008 4:28:02 AM
10 January 2009 (4 Months To

go)

1/10/2009 4:28:02 AM
28 August 2009 8/28/2009 4:28:02 AM

Few points to note about this method

  • If the date is older or newer than 12 months, it will output full date string. This is because I feel the relative time does not have much relevance beyond a certain threshold. You can always change the method to suit your needs.
  • It does not display the year if the time is in the same year as the RelativeTo time.
  • It will automatically add “ago” or “to go” at end of the output depending on whether the time is less than or greater than the relative to time.
  • The method is implemented as a static method not as an extension method, so that it works in .net 2.0 as well. However, if you are using .net 3.5 then you can easily convert the code to an extension method for easier use.

The code follows

//The overload which takes only the time to process. The second parameter defaults to DateTime.UtcNow
public static string ToRelativeTimeString(DateTime time)
{
return ToRelativeTimeString(time, DateTime.UtcNow);
}

//The overload which take both the parameters
public static string ToRelativeTimeString(DateTime time,DateTime RelativeTo)
{
TimeSpan ts = RelativeTo.Subtract(time).Duration();
string DateFormat=”d MMMM”;
string dir=(RelativeTo>time)?”Ago”:”To go”;
if(RelativeTo.Year!=time.Year)
DateFormat += ” yyyy”;
if(ts.Days <360)
{
//Months
if(ts.Days >=30)
return string.Format( “{0} ({1} Months {2})”, time.ToString(DateFormat), (int)(ts.Days /30),dir );
//Days
if(ts.Days >0)
return string.Format(”{0} ({1} Days {2})”, time.ToString(DateFormat), ts.Days ,dir );
//hours
if(ts.Hours>0)
return string.Format(”{0} Hours {1} Minutes {2}”, ts.Hours ,ts.Minutes , dir);
//minutes
if(ts.Minutes>0)
return string.Format(”{0} Minutes {1} Seconds {2}”, ts.Minutes ,ts.Seconds , dir);
//seconds
return string.Format(”{0} Seconds {1}”, ts.Seconds , dir);
}
return time.ToString(DateFormat);
}

Using the code

Using this method is very easy. Just call the ToRelativeTimeString() method passing it the DateTime to process.

Response.Write( ToRelativeTimeString( dt));

I also ran a quick and dirty performance test by calling this function with randomly generated dates 100000 times and results were surprising or at least was not what I expected. This function was equal in performance to DateTime.ToLongDateString() some times even beating it while processing dates lesser than a day. It was slightly expensive while processing dates older than a year as expected because after doing all the processing, it was using DateTime.ToString() with some custom date formatting to return the result. Still the extra overhead is really small (0.3 sec vs 0.35 sec for processing it 100000 times!).

Happy coding!


If you liked this post, please subscribe to this blog or kick this story on DotNetKicks.com .

Tags: ,

You can leave a response, or trackback from your own site.

6 Responses to “Displaying time in relative format”

  1. Ryan Says:

    Thank you for writing this! I have a project I’m working on right now where I was looking into doing just this sort of thing. You’ve saved me a lot of work!

  2. Niran Says:

    Good to know that it helped you.
    All the best for the project,
    Nirandas

  3. Marco Says:

    Nice! let’s try to translate it using the CurrentCulture setting

  4. Roger Dickey Says:

    Perfect timing! Thanks for the handy snippet!

  5. Anders Says:

    I believe that you have to use Total*** or else you will get the wrong output.

    if(ts.TotalDays < 360) and so on..

  6. Niran Says:

    @Anders
    In this case there is no need to use Total** methods as the timespan has already been converted to a positive timespan by calling the duration() method.
    TimeSpan ts = RelativeTo.Subtract(time).Duration();
    Hence in this case, the TotalDays and days would return the difference between the 2 dates as a positive value.
    Nirandas

Leave a Reply


© 2008 By Nirandas, All rights reserved.