Dot Net Perls

Pretty Date Formatting - C#

by Sam Allen

Problem

You want to display pretty, nicely formatted dates in your C# program. For example, you need to show "1 hour ago" or "1 minute ago", instead of seconds. Use existing and tested code, adapted to C#.

Solution: using pretty dates in C#

Prettily formatted dates are sometimes overlooked in ASP.NET or Windows applications. They are a final touch that can really make your app look excellent.

For my code, I wanted a standard method that was established. For this reason, I adapted John Resig's code. He uses this for AJAX and client-side pages.

Information: implementing pretty dates in C#

To display usable relative and pretty dates, you need to calculate the time elapsed from the original date. So the method here receives the original DateTime, and then uses DateTime.Now to calculate the elapsed time.

using System;

class Program
{
    static void Main()
    {
        // Test 90 seconds ago.
        Console.WriteLine(GetPrettyDate(DateTime.Now.AddSeconds(-90)));
        // Test 25 minutes ago.
        Console.WriteLine(GetPrettyDate(DateTime.Now.AddMinutes(-25)));
        // Test 45 minutes ago.
        Console.WriteLine(GetPrettyDate(DateTime.Now.AddMinutes(-45)));
        // Test 4 hours ago.
        Console.WriteLine(GetPrettyDate(DateTime.Now.AddHours(-4)));
        // Test 15 days ago.
        Console.WriteLine(GetPrettyDate(DateTime.Now.AddDays(-15)));
    }

    static string GetPrettyDate(DateTime d)
    {
        // 1.
        // Get time span elapsed since the date.
        TimeSpan s = DateTime.Now.Subtract(d);

        // 2.
        // Get total number of days elapsed.
        int dayDiff = (int)s.TotalDays;

        // 3.
        // Get total number of seconds elapsed.
        int secDiff = (int)s.TotalSeconds;

        // 4.
        // Don't allow out of range values.
        if (dayDiff < 0 || dayDiff >= 31)
        {
            return null;
        }

        // 5.
        // Handle same-day times.
        if (dayDiff == 0)
        {
            // A.
            // Less than one minute ago.
            if (secDiff < 60)
            {
                return "just now";
            }
            // B.
            // Less than 2 minutes ago.
            if (secDiff < 120)
            {
                return "1 minute ago";
            }
            // C.
            // Less than one hour ago.
            if (secDiff < 3600)
            {
                return string.Format("{0} minutes ago",
                    Math.Floor((double)secDiff / 60));
            }
            // D.
            // Less than 2 hours ago.
            if (secDiff < 7200)
            {
                return "1 hour ago";
            }
            // E.
            // Less than one day ago.
            if (secDiff < 86400)
            {
                return string.Format("{0} hours ago",
                    Math.Floor((double)secDiff / 3600));
            }
        }
        // 6.
        // Handle previous days.
        if (dayDiff == 1)
        {
            return "yesterday";
        }
        if (dayDiff < 7)
        {
            return string.Format("{0} days ago",
                dayDiff);
        }
        if (dayDiff < 31)
        {
            return string.Format("{0} weeks ago",
                Math.Ceiling((double)dayDiff / 7));
        }
        return null;
    }
}

First we see the Main method, which simply tests the method for accuracy. We can establish that the method works by its output.

Steps 1 - 3 in the GetPrettyDate method simply take the elapsed days and seconds from the original date. This a standard way to calculate elapsed time. Note that TotalDays and TotalSeconds are used. [C# - Get Elapsed Days From DateTime - dotnetperls.com]

Step 5 handles very recent dates, in the same day. You can see in parts A - E that there is a chain of conditionals that return pretty strings.

Finally, step 6 handles more distant dates. Note that the method, as does the original by John Resig, doesn't handle months and years.

Task: testing the code

From running the above program, we get the following output. You can see that it underestimates the smaller elapsed times and overestimates the larger values. This is by design.

1 minute ago
25 minutes ago
45 minutes ago
4 hours ago
3 weeks ago

Task: reading the original code

I wanted to closely follow the logic in the original pretty.js JavaScript code, because I felt it would be best to follow the same rules. This way, you can swap the two methods and use one on the ASP.NET server and the other in JavaScript. [JavaScript Pretty Date - ejohn.org]

Additionally, David Longnecker shows on his blog another method that uses similar logic to calculate Twitter-like dates. His algorithm would perform better in a benchmark, as it uses string.Concat instead of string.Format. However, it might be harder to make adjustments to. [Creating Twitter-esque Relative Dates in C# - tiredblogger.wordpress.com]

Question: where are the pretty dates? I just see code

Sorry to inconvenience you. I found pretty dates when I was looking for code. I wish you luck in finding a partner, but Google might not be the best spot to look.

Summary: formatting relative dates in C#

This code is mainly a finishing touch for your applications. It is something that I wished I had when rushing to complete a project.

Thanks to John Resig for the original code and inspiration. His code is under the MIT license, but I put the C# code on this page in the public domain.

Dot Net Perls
About
Sitemap
DateTime
DateTime Tips and Tricks
Pretty Date Formatting
Use DateTime for Filenames
FromOADate and Excel Dates
Get Days Elapsed From DateTime
New
GZIP Accept-Encoding Request
Convert bool to int
© 2008 Sam Allen. All rights reserved.