1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
public static string ToRelativeDate(DateTime input) { string suffix = "ago"; TimeSpan difference = (DateTime.Now - input); double millisecondsDifference = difference.TotalMilliseconds; if ((millisecondsDifference < 0)) { suffix = "from now"; millisecondsDifference = Math.Abs(millisecondsDifference); } double seconds = millisecondsDifference / 1000; double minutes = seconds / 60; double hours = minutes / 60; double days = hours / 24; double years = days / 365; string relativeDate = string.Empty; if ((seconds < 45)) { relativeDate = "less than a minute"; } else if ((seconds < 90)) { relativeDate = "about a minute"; } else if ((minutes < 45)) { relativeDate = string.Format("{0} minutes", Math.Round(minutes)); } else if ((minutes < 90)) { relativeDate = "about an hour"; } else if ((hours < 24)) { relativeDate = string.Format("about {0} hours", Math.Round(hours)); } else if ((hours < 48)) { relativeDate = "a day"; } else if ((days < 30)) { relativeDate = string.Format("{0} days", Math.Floor(days)); } else if ((days < 60)) { relativeDate = "about a month"; } else if ((days < 365)) { relativeDate = string.Format("{0} months", Math.Floor(days / 30)); } else if ((years < 2)) { relativeDate = "about a year"; } else { relativeDate = string.Format("{0} years", Math.Floor(years)); } return relativeDate + " " + suffix; }
Refactorings
No refactoring yet !
Moonshield
September 16, 2008, September 16, 2008 02:10, permalink
I came up with that. It uses .Net 3.5
You can also extend to DateTime object to include this method but I won't cover that as there are plenty of exemple on how to do it on here.
Hope you like it :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
public static string ToRelativeDate(DateTime input) { TimeSpan oSpan = DateTime.Now.Subtract(input); double TotalMinutes = oSpan.TotalMinutes; string Suffix = " ago"; if (TotalMinutes < 0.0) { TotalMinutes = Math.Abs(TotalMinutes); Suffix = " from now"; } Dictionary<double, Func<string>> aValue = new Dictionary<double, Func<string>>(); aValue.Add(0.75, () => "less than a minute"); aValue.Add(1.5, () => "about a minute"); aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes))); aValue.Add(90, () => "about an hour"); aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24 aValue.Add(2880, () => "a day"); // 60 * 48 aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30 aValue.Add(86400, () => "about a month"); // 60 * 24 * 60 aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2 aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365)))); return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix; }
Joseph Kingry
November 11, 2008, November 11, 2008 15:18, permalink
Liked the use of functions, but wanted to have the mapping be a static structure so used a static constructor.
C# specification specifies that constant folding must be implemented so expanded the multiplication
Made it an extension (trivial I know)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
namespace Example { using System; using System.Collections.Generic; using System.Linq; public static class DateTimeExtension { static readonly Dictionary<double, Func<TimeSpan, string>> relativeDateMap; static DateTimeExtension() { relativeDateMap = new Dictionary<double, Func<TimeSpan, string>> { { 0.75, x => "less than a minute" }, { 1.5, x => "about a minute" }, { 45, x => String.Format("{0} minutes", Math.Abs(x.TotalMinutes)) }, { 90, x => "about an hour" }, { 60 * 24, x => String.Format("about {0} hours", Math.Round(Math.Abs(x.TotalHours))) }, // { 60 * 48, x => "a day" }, { 60 * 24 * 30, x => String.Format("{0} days", Math.Floor(Math.Abs(x.TotalDays))) }, { 60 * 24 * 60, x => "about a month" }, { 60 * 24 * 365, x => String.Format("{0} months", Math.Floor(Math.Abs(x.TotalDays / 30))) }, { 60 * 24 * 365 * 2, x => "about a year" }, { Double.MaxValue, x => String.Format("{0} years", Math.Floor(Math.Abs(x.TotalDays / 365))) } }; } public static string ToRelativeDate(this DateTime input) { TimeSpan diff = DateTime.Now.Subtract(input); double totalMinutes = diff.TotalMinutes; string suffix = " ago"; if (totalMinutes < 0.0) { totalMinutes = Math.Abs(totalMinutes); suffix = " from now"; } return relativeDateMap.First(n => totalMinutes < n.Key).Value(diff) + suffix; } } }
Given an input date, this method will return a human-like description based on the difference between the input date and now.
For example :
3 days from now
about a month ago
Was just wondering if there was a better way of doing this ?
Thanks