9

Does anyone have a simple function at hand for converting a date to a simple date-relative string in .NET?

E.g. 14-Oct-09 would read "Today", 13-Oct-09 would read "Yesterday" and 7-Oct-09 would read "1 Week Ago" etc.

zcoop98
  • 2,590
  • 1
  • 18
  • 31
TimS
  • 5,922
  • 6
  • 35
  • 55
  • Interesting take. I'm not certain you're going to get any answer beyond "roll your own" :) – JustLoren Oct 14 '09 at 14:08
  • 5
    One of the very first questions on this site dealt with this issue: http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time – Fredrik Mörk Oct 14 '09 at 14:12
  • And for a way of achieving this in SQL (should you ever want to): http://stackoverflow.com/questions/50149/best-way-to-convert-datetime-to-n-hours-ago-in-sql – CraigTP Oct 14 '09 at 14:14
  • Does this answer your question? [Calculate relative time in C#](https://stackoverflow.com/questions/11/calculate-relative-time-in-c-sharp) – zcoop98 Jan 28 '22 at 21:39

2 Answers2

9

You would indeed have to roll your own method of doing this, like JustLoren said.

This is an extension method I've been using. It is GateKiller script made into an extension method. So full credit to him. You could easily change it to however you want it.

public static string ToTimeSinceString(this DateTime value)
{
    const int SECOND = 1;
    const int MINUTE = 60 * SECOND;
    const int HOUR = 60 * MINUTE;
    const int DAY = 24 * HOUR;
    const int MONTH = 30 * DAY;

    TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - value.Ticks);
    double seconds = ts.TotalSeconds;

    // Less than one minute
    if (seconds < 1 * MINUTE)
        return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";

    if (seconds < 60 * MINUTE)
        return ts.Minutes + " minutes ago";

    if (seconds < 120 * MINUTE)
        return "an hour ago";

    if (seconds < 24 * HOUR)
        return ts.Hours + " hours ago";

    if (seconds < 48 * HOUR)
        return "yesterday";

    if (seconds < 30 * DAY)
        return ts.Days + " days ago";

    if (seconds < 12 * MONTH) {
        int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
        return months <= 1 ? "one month ago" : months + " months ago";
    }

    int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
    return years <= 1 ? "one year ago" : years + " years ago";
}
Community
  • 1
  • 1
aolde
  • 2,287
  • 16
  • 19
  • That seems to come straight from the accepted answer on the question I linked to in the question comments ;o) – Fredrik Mörk Oct 14 '09 at 14:19
  • Really sorry about that. I had forgotten where it came from. Added credit to answer. – aolde Oct 14 '09 at 14:26
  • You should probably use `DateTime.UtcNow.Ticks` instead of `.Now` to stay in line with best practices assuming your DB is storing stuff in UTC. – James Reategui Dec 11 '11 at 01:42
6

Something like this extension method?

public static string Stringfy(this DateTime date)
{
    if ((DateTime.Now - date.Date).TotalDays == 0)
        return "Today";

    if ((DateTime.Now - date.Date).TotalDays == 1)
        return "Yesterday";

    // ...

    return "A long time ago, in a galaxy far far away...";
}
Rubens Farias
  • 57,174
  • 8
  • 131
  • 162
  • Isn't TotalDays a double? Maybe a Truncate is in order to get the whole days or even use DateTime.Now.Date instead of DateTime.Now – Darren Sep 20 '12 at 06:52