Smart Relative date formatting in C# using extension methods.
The C# DateTime object has some nice .ToString() overloads for formatting dates but sometimes we would like a friendly, relative format like what you see in many Android or iPhone apps.
The idea is to only include year, month, and day when they are not the current one. Examples are as follows...
Just now
55 seconds ago
1 min ago
15 mins ago
1 hour ago
13 hours ago
Sunday, 25th at 12:53 PM - different day, same month
Tuesday, May 2nd at 12:53 PM - difference month, same year
May 2nd, 2016 at 12:53 PM - different year
I like this format because it's flexible enough to give you a nice relative format that scales well with dates far in the past. To implement, I used an extension method. Since I am using ordinals for the days, I used another extension that I found in a Stack Overflow post. The Humanizr library accomplishes ordinals very well, but in this case I found it to be overkill.
All code below. Now put it into action in your User Interfaces!
The idea is to only include year, month, and day when they are not the current one. Examples are as follows...
Just now
55 seconds ago
1 min ago
15 mins ago
1 hour ago
13 hours ago
Sunday, 25th at 12:53 PM - different day, same month
Tuesday, May 2nd at 12:53 PM - difference month, same year
May 2nd, 2016 at 12:53 PM - different year
I like this format because it's flexible enough to give you a nice relative format that scales well with dates far in the past. To implement, I used an extension method. Since I am using ordinals for the days, I used another extension that I found in a Stack Overflow post. The Humanizr library accomplishes ordinals very well, but in this case I found it to be overkill.
All code below. Now put it into action in your User Interfaces!
public static class DateTimeExtensions
{
public static String ToRelativeFormat(this DateTime dateTime)
{
var now = DateTime.Now;
var timeDifference = now - dateTime;
var daySuffix = GetDaySuffix(dateTime);
if (now.Year == dateTime.Year)
{
// exclude year
if (now.Month == dateTime.Month)
{
// exclude month
if (now.Day == dateTime.Day)
{
// exclude day
if (timeDifference.Hours < 24)
{
// display as hours
if (timeDifference.Hours < 1)
{
// display as minutes
if (timeDifference.Minutes < 1)
{
// display as seconds
if (timeDifference.Seconds <= 1)
return "Just now";
return timeDifference.Seconds + " seconds ago";
}
if (timeDifference.Minutes == 1)
{
return timeDifference.Minutes + " minute ago";
}
// display as minutes
return timeDifference.Minutes + " minutes ago";
}
// display as hours
if (timeDifference.Hours == 1)
return "1 hour ago";
return timeDifference.Hours + " hours ago";
}
}
// display with year and month excluded
return dateTime.ToString($"dddd, d'{daySuffix}' 'at' h:mm tt");
}
// display with year excluded
return dateTime.ToString($"dddd, MMMM d'{daySuffix}' 'at' h:mm tt");
}
// display with name of day excluded
return dateTime.ToString($"MMMM d'{daySuffix}', yyyy 'at' h:mm tt");
}
#region HELPERS
private static String GetDaySuffix(DateTime date)
{
return date.Day.ToOrdinal();
}
#endregion
}
public static class NumericExtensions
{
// Taken from: http://stackoverflow.com/questions/2050805/getting-day-suffix-when-using-datetime-tostring
public static String ToOrdinal(this Int32 value)
{
var ordinal = "";
switch (value)
{
case 1:
case 21:
case 31:
ordinal = "st";
break;
case 2:
case 22:
ordinal = "nd";
break;
case 3:
case 23:
ordinal = "rd";
break;
default:
ordinal = "th";
break;
}
return ordinal;
}
}
Comments
Post a Comment