Ed581b36edb9fa8f4c46e7ebef6b2fc5

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

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 !

Avatar

Moonshield

September 16, 2008, September 16, 2008 02:10, permalink

1 rating. Login to rate!

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;
}
Ed581b36edb9fa8f4c46e7ebef6b2fc5

Foxx

September 16, 2008, September 16, 2008 06:48, permalink

No rating. Login to rate!

Wow .. Thats all I can say

A5fd8bb6c4cb5fcd9d16d39e80ca0514

Joseph Kingry

November 11, 2008, November 11, 2008 15:18, permalink

1 rating. Login to rate!

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;
        }
    }
}

Your refactoring





Format Copy from initial code

or Cancel