<p>Given a specific <code>DateTime</code> value, how do I display relative time, like:</p>
<ul>
<li><code>2 hours ago</code></li>
<li><code>3 days ago</code></li>
<li><code>a month ago</code></li>
</ul>

[{'answer_id': 12, 'author': 'Jeff Atwood', 'author_id': 1, 'author_profile': 'https://Stackoverflow.com/users/1', 'pm_score': 8, 'selected': False, 'text': '<p>Here\'s how I do it</p>\n\n<pre class="lang-csharp prettyprint-override"><code>var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);\ndouble delta = Math.Abs(ts.TotalSeconds);\n\nif (delta &lt; 60)\n{\n  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";\n}\nif (delta &lt; 60 * 2)\n{\n  return "a minute ago";\n}\nif (delta &lt; 45 * 60)\n{\n  return ts.Minutes + " minutes ago";\n}\nif (delta &lt; 90 * 60)\n{\n  return "an hour ago";\n}\nif (delta &lt; 24 * 60 * 60)\n{\n  return ts.Hours + " hours ago";\n}\nif (delta &lt; 48 * 60 * 60)\n{\n  return "yesterday";\n}\nif (delta &lt; 30 * 24 * 60 * 60)\n{\n  return ts.Days + " days ago";\n}\nif (delta &lt; 12 * 30 * 24 * 60 * 60)\n{\n  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));\n  return months &lt;= 1 ? "one month ago" : months + " months ago";\n}\nint years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));\nreturn years &lt;= 1 ? "one year ago" : years + " years ago";\n</code></pre>\n\n<p>Suggestions? Comments? Ways to improve this algorithm?</p>\n'}, {'answer_id': 27, 'author': 'Nick Berardi', 'author_id': 17, 'author_profile': 'https://Stackoverflow.com/users/17', 'pm_score': 5, 'selected': False, 'text': '<p>@jeff</p>\n<p>IMHO yours seems a little long. However it does seem a little more robust with support for &quot;yesterday&quot; and &quot;years&quot;.  But in my experience when this is used, the person is most likely to view the content in the first 30 days. It is only the really hardcore people that come after that. So, I usually elect to keep this short and simple.</p>\n<p>This is the method I am currently using in one of my websites. This returns only a relative day, hour and time.  And then the user has to slap on &quot;ago&quot; in the output.</p>\n<pre><code>public static string ToLongString(this TimeSpan time)\n{\n    string output = String.Empty;\n\n    if (time.Days &gt; 0)\n        output += time.Days + &quot; days &quot;;\n\n    if ((time.Days == 0 || time.Days == 1) &amp;&amp; time.Hours &gt; 0)\n        output += time.Hours + &quot; hr &quot;;\n\n    if (time.Days == 0 &amp;&amp; time.Minutes &gt; 0)\n        output += time.Minutes + &quot; min &quot;;\n\n    if (output.Length == 0)\n        output += time.Seconds + &quot; sec&quot;;\n\n    return output.Trim();\n}\n</code></pre>\n'}, {'answer_id': 1248, 'author': 'Vincent Robert', 'author_id': 268, 'author_profile': 'https://Stackoverflow.com/users/268', 'pm_score': 11, 'selected': True, 'text': '<p>Jeff, <a href="https://stackoverflow.com/questions/11/how-do-i-calculate-relative-time/12#12">your code</a> is nice but could be clearer with constants (as suggested in Code Complete).</p>\n\n<pre class="lang-csharp prettyprint-override"><code>const int SECOND = 1;\nconst int MINUTE = 60 * SECOND;\nconst int HOUR = 60 * MINUTE;\nconst int DAY = 24 * HOUR;\nconst int MONTH = 30 * DAY;\n\nvar ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);\ndouble delta = Math.Abs(ts.TotalSeconds);\n\nif (delta &lt; 1 * MINUTE)\n  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";\n\nif (delta &lt; 2 * MINUTE)\n  return "a minute ago";\n\nif (delta &lt; 45 * MINUTE)\n  return ts.Minutes + " minutes ago";\n\nif (delta &lt; 90 * MINUTE)\n  return "an hour ago";\n\nif (delta &lt; 24 * HOUR)\n  return ts.Hours + " hours ago";\n\nif (delta &lt; 48 * HOUR)\n  return "yesterday";\n\nif (delta &lt; 30 * DAY)\n  return ts.Days + " days ago";\n\nif (delta &lt; 12 * MONTH)\n{\n  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));\n  return months &lt;= 1 ? "one month ago" : months + " months ago";\n}\nelse\n{\n  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));\n  return years &lt;= 1 ? "one year ago" : years + " years ago";\n}\n</code></pre>\n'}, {'answer_id': 1752, 'author': 'Wedge', 'author_id': 332, 'author_profile': 'https://Stackoverflow.com/users/332', 'pm_score': 4, 'selected': False, 'text': '<p>I thought I\'d give this a shot using classes and polymorphism. I had a previous iteration which used sub-classing which ended up having way too much overhead. I\'ve switched to a more flexible delegate / public property object model which is significantly better. My code is very slightly more accurate, I wish I could come up with a better way to generate "months ago" that didn\'t seem too over-engineered.</p>\n\n<p>I think I\'d still stick with Jeff\'s if-then cascade because it\'s less code and it\'s simpler (it\'s definitely easier to ensure it\'ll work as expected).</p>\n\n<p>For the below code <em>PrintRelativeTime.GetRelativeTimeMessage(TimeSpan ago)</em> returns the relative time message (e.g. "yesterday").</p>\n\n<pre><code>public class RelativeTimeRange : IComparable\n{\n    public TimeSpan UpperBound { get; set; }\n\n    public delegate string RelativeTimeTextDelegate(TimeSpan timeDelta);\n\n    public RelativeTimeTextDelegate MessageCreator { get; set; }\n\n    public int CompareTo(object obj)\n    {\n        if (!(obj is RelativeTimeRange))\n        {\n            return 1;\n        }\n        // note that this sorts in reverse order to the way you\'d expect, \n        // this saves having to reverse a list later\n        return (obj as RelativeTimeRange).UpperBound.CompareTo(UpperBound);\n    }\n}\n\npublic class PrintRelativeTime\n{\n    private static List&lt;RelativeTimeRange&gt; timeRanges;\n\n    static PrintRelativeTime()\n    {\n        timeRanges = new List&lt;RelativeTimeRange&gt;{\n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromSeconds(1),\n                MessageCreator = (delta) =&gt; \n                { return "one second ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromSeconds(60),\n                MessageCreator = (delta) =&gt; \n                { return delta.Seconds + " seconds ago"; }\n\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromMinutes(2),\n                MessageCreator = (delta) =&gt; \n                { return "one minute ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromMinutes(60),\n                MessageCreator = (delta) =&gt; \n                { return delta.Minutes + " minutes ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromHours(2),\n                MessageCreator = (delta) =&gt; \n                { return "one hour ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromHours(24),\n                MessageCreator = (delta) =&gt; \n                { return delta.Hours + " hours ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.FromDays(2),\n                MessageCreator = (delta) =&gt; \n                { return "yesterday"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),\n                MessageCreator = (delta) =&gt; \n                { return delta.Days + " days ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),\n                MessageCreator = (delta) =&gt; \n                { return "one month ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),\n                MessageCreator = (delta) =&gt; \n                { return (int)Math.Floor(delta.TotalDays / 30) + " months ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),\n                MessageCreator = (delta) =&gt; \n                { return "one year ago"; }\n            }, \n            new RelativeTimeRange\n            {\n                UpperBound = TimeSpan.MaxValue,\n                MessageCreator = (delta) =&gt; \n                { return (int)Math.Floor(delta.TotalDays / 365.24D) + " years ago"; }\n            }\n        };\n\n        timeRanges.Sort();\n    }\n\n    public static string GetRelativeTimeMessage(TimeSpan ago)\n    {\n        RelativeTimeRange postRelativeDateRange = timeRanges[0];\n\n        foreach (var timeRange in timeRanges)\n        {\n            if (ago.CompareTo(timeRange.UpperBound) &lt;= 0)\n            {\n                postRelativeDateRange = timeRange;\n            }\n        }\n\n        return postRelativeDateRange.MessageCreator(ago);\n    }\n}\n</code></pre>\n'}, {'answer_id': 10705, 'author': 'DevelopingChris', 'author_id': 1220, 'author_profile': 'https://Stackoverflow.com/users/1220', 'pm_score': 7, 'selected': False, 'text': '<pre class="lang-csharp prettyprint-override"><code>public static string RelativeDate(DateTime theDate)\n{\n    Dictionary&lt;long, string&gt; thresholds = new Dictionary&lt;long, string&gt;();\n    int minute = 60;\n    int hour = 60 * minute;\n    int day = 24 * hour;\n    thresholds.Add(60, "{0} seconds ago");\n    thresholds.Add(minute * 2, "a minute ago");\n    thresholds.Add(45 * minute, "{0} minutes ago");\n    thresholds.Add(120 * minute, "an hour ago");\n    thresholds.Add(day, "{0} hours ago");\n    thresholds.Add(day * 2, "yesterday");\n    thresholds.Add(day * 30, "{0} days ago");\n    thresholds.Add(day * 365, "{0} months ago");\n    thresholds.Add(long.MaxValue, "{0} years ago");\n    long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;\n    foreach (long threshold in thresholds.Keys) \n    {\n        if (since &lt; threshold) \n        {\n            TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks));\n            return string.Format(thresholds[threshold], (t.Days &gt; 365 ? t.Days / 365 : (t.Days &gt; 0 ? t.Days : (t.Hours &gt; 0 ? t.Hours : (t.Minutes &gt; 0 ? t.Minutes : (t.Seconds &gt; 0 ? t.Seconds : 0))))).ToString());\n        }\n    }\n    return "";\n}\n</code></pre>\n\n<p>I prefer this version for its conciseness, and ability to add in new tick points.\nThis could be encapsulated with a <code>Latest()</code> extension to Timespan instead of that long 1 liner, but for the sake of brevity in posting, this will do.\n<strong>This fixes the an hour ago, 1 hours ago, by providing an hour until 2 hours have elapsed</strong></p>\n'}, {'answer_id': 12279, 'author': 'Will Dean', 'author_id': 987, 'author_profile': 'https://Stackoverflow.com/users/987', 'pm_score': 4, 'selected': False, 'text': '<p>@Jeff</p>\n\n<blockquote>\n<pre><code>var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);\n</code></pre>\n</blockquote>\n\n<p>Doing a subtraction on <code>DateTime</code> returns a <code>TimeSpan</code> anyway.</p>\n\n<p>So you can just do </p>\n\n<pre class="lang-cs prettyprint-override"><code>(DateTime.UtcNow - dt).TotalSeconds\n</code></pre>\n\n<p>I\'m also surprised to see the constants multiplied-out by hand and then comments added with the multiplications in.   Was that some misguided optimisation?</p>\n'}, {'answer_id': 12852, 'author': 'markpasc', 'author_id': 1472, 'author_profile': 'https://Stackoverflow.com/users/1472', 'pm_score': 4, 'selected': False, 'text': '<p>When you know the viewer\'s time zone, it might be clearer to use calendar days at the day scale. I\'m not familiar with the .NET libraries so I don\'t know how you\'d do that in C#, unfortunately.</p>\n\n<p>On consumer sites, you could also be hand-wavier under a minute. "Less than a minute ago" or "just now" could be good enough.</p>\n'}, {'answer_id': 13690, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 4, 'selected': False, 'text': '<p>You can reduce the server-side load by performing this logic client-side. View source on some Digg pages for reference. They have the server emit an epoch time value that gets processed by Javascript. This way you don\'t need to manage the end user\'s time zone. The new server-side code would be something like:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public string GetRelativeTime(DateTime timeStamp)\n{\n    return string.Format("&lt;script&gt;printdate({0});&lt;/script&gt;", timeStamp.ToFileTimeUtc());\n}\n</code></pre>\n\n<p>You could even add a NOSCRIPT block there and just perform a ToString().</p>\n'}, {'answer_id': 18393, 'author': 'icco', 'author_id': 1063, 'author_profile': 'https://Stackoverflow.com/users/1063', 'pm_score': 4, 'selected': False, 'text': '<p>In PHP, I do it this way: </p>\n\n<pre class="lang-php prettyprint-override"><code>&lt;?php\nfunction timesince($original) {\n    // array of time period chunks\n    $chunks = array(\n        array(60 * 60 * 24 * 365 , \'year\'),\n        array(60 * 60 * 24 * 30 , \'month\'),\n        array(60 * 60 * 24 * 7, \'week\'),\n        array(60 * 60 * 24 , \'day\'),\n        array(60 * 60 , \'hour\'),\n        array(60 , \'minute\'),\n    );\n\n    $today = time(); /* Current unix time  */\n    $since = $today - $original;\n\n    if($since &gt; 604800) {\n    $print = date("M jS", $original);\n\n    if($since &gt; 31536000) {\n        $print .= ", " . date("Y", $original);\n    }\n\n    return $print;\n}\n\n// $j saves performing the count function each time around the loop\nfor ($i = 0, $j = count($chunks); $i &lt; $j; $i++) {\n\n    $seconds = $chunks[$i][0];\n    $name = $chunks[$i][1];\n\n    // finding the biggest chunk (if the chunk fits, break)\n    if (($count = floor($since / $seconds)) != 0) {\n        break;\n    }\n}\n\n$print = ($count == 1) ? \'1 \'.$name : "$count {$name}s";\n\nreturn $print . " ago";\n\n} ?&gt;\n</code></pre>\n'}, {'answer_id': 25709, 'author': 'Cebjyre', 'author_id': 1612, 'author_profile': 'https://Stackoverflow.com/users/1612', 'pm_score': 2, 'selected': False, 'text': '<p>Surely an easy fix to get rid of the \'1 hours ago\' problem would be to increase the window that \'an hour ago\' is valid for.\nChange</p>\n\n<pre><code>if (delta &lt; 5400) // 90 * 60\n{\n    return "an hour ago";\n}\n</code></pre>\n\n<p>into</p>\n\n<pre><code>if (delta &lt; 7200) // 120 * 60\n{\n    return "an hour ago";\n}\n</code></pre>\n\n<p>This means that something that occurred 110 minutes ago will read as \'an hour ago\' - this may not be perfect, but I\'d say it is better than the current situation of \'1 hours ago\'. </p>\n'}, {'answer_id': 79601, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 6, 'selected': False, 'text': '<pre class="lang-csharp prettyprint-override"><code>public static string ToRelativeDate(DateTime input)\n{\n    TimeSpan oSpan = DateTime.Now.Subtract(input);\n    double TotalMinutes = oSpan.TotalMinutes;\n    string Suffix = " ago";\n\n    if (TotalMinutes &lt; 0.0)\n    {\n        TotalMinutes = Math.Abs(TotalMinutes);\n        Suffix = " from now";\n    }\n\n    var aValue = new SortedList&lt;double, Func&lt;string&gt;&gt;();\n    aValue.Add(0.75, () =&gt; "less than a minute");\n    aValue.Add(1.5, () =&gt; "about a minute");\n    aValue.Add(45, () =&gt; string.Format("{0} minutes", Math.Round(TotalMinutes)));\n    aValue.Add(90, () =&gt; "about an hour");\n    aValue.Add(1440, () =&gt; string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24\n    aValue.Add(2880, () =&gt; "a day"); // 60 * 48\n    aValue.Add(43200, () =&gt; string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30\n    aValue.Add(86400, () =&gt; "about a month"); // 60 * 24 * 60\n    aValue.Add(525600, () =&gt; string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 \n    aValue.Add(1051200, () =&gt; "about a year"); // 60 * 24 * 365 * 2\n    aValue.Add(double.MaxValue, () =&gt; string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));\n\n    return aValue.First(n =&gt; TotalMinutes &lt; n.Key).Value.Invoke() + Suffix;\n}\n</code></pre>\n\n<p><a href="http://refactormycode.com/codes/493-twitter-esque-relative-dates" rel="noreferrer">http://refactormycode.com/codes/493-twitter-esque-relative-dates</a></p>\n\n<p>C# 6 version:</p>\n\n<pre><code>static readonly SortedList&lt;double, Func&lt;TimeSpan, string&gt;&gt; offsets = \n   new SortedList&lt;double, Func&lt;TimeSpan, string&gt;&gt;\n{\n    { 0.75, _ =&gt; "less than a minute"},\n    { 1.5, _ =&gt; "about a minute"},\n    { 45, x =&gt; $"{x.TotalMinutes:F0} minutes"},\n    { 90, x =&gt; "about an hour"},\n    { 1440, x =&gt; $"about {x.TotalHours:F0} hours"},\n    { 2880, x =&gt; "a day"},\n    { 43200, x =&gt; $"{x.TotalDays:F0} days"},\n    { 86400, x =&gt; "about a month"},\n    { 525600, x =&gt; $"{x.TotalDays / 30:F0} months"},\n    { 1051200, x =&gt; "about a year"},\n    { double.MaxValue, x =&gt; $"{x.TotalDays / 365:F0} years"}\n};\n\npublic static string ToRelativeDate(this DateTime input)\n{\n    TimeSpan x = DateTime.Now - input;\n    string Suffix = x.TotalMinutes &gt; 0 ? " ago" : " from now";\n    x = new TimeSpan(Math.Abs(x.Ticks));\n    return offsets.First(n =&gt; x.TotalMinutes &lt; n.Key).Value(x) + Suffix;\n}\n</code></pre>\n'}, {'answer_id': 111303, 'author': 'Ryan McGeary', 'author_id': 8985, 'author_profile': 'https://Stackoverflow.com/users/8985', 'pm_score': 9, 'selected': False, 'text': '<h2><a href="https://timeago.yarp.com/" rel="noreferrer">jquery.timeago plugin</a></h2>\n\n<p>Jeff, because Stack Overflow uses jQuery extensively, I recommend the <a href="https://timeago.yarp.com/" rel="noreferrer">jquery.timeago plugin</a>.  </p>\n\n<p>Benefits:</p>\n\n<ul>\n<li>Avoid timestamps dated "1 minute ago" even though the page was opened 10 minutes ago; timeago refreshes automatically.</li>\n<li>You can take full advantage of page and/or fragment caching in your web applications, because the timestamps aren\'t calculated on the server.</li>\n<li>You get to use microformats like the cool kids.</li>\n</ul>\n\n<p>Just attach it to your timestamps on DOM ready:</p>\n\n<pre class="lang-js prettyprint-override"><code>jQuery(document).ready(function() {\n    jQuery(\'abbr.timeago\').timeago();\n});\n</code></pre>\n\n<p>This will turn all <code>abbr</code> elements with a class of timeago and an <a href="https://en.wikipedia.org/wiki/ISO_8601" rel="noreferrer">ISO 8601</a> timestamp in the title:</p>\n\n<pre class="lang-html prettyprint-override"><code>&lt;abbr class="timeago" title="2008-07-17T09:24:17Z"&gt;July 17, 2008&lt;/abbr&gt;\n</code></pre>\n\n<p>into something like this:</p>\n\n<pre class="lang-html prettyprint-override"><code>&lt;abbr class="timeago" title="July 17, 2008"&gt;4 months ago&lt;/abbr&gt;\n</code></pre>\n\n<p>which yields: 4 months ago. As time passes, the timestamps will automatically update. </p>\n\n<p><em>Disclaimer: I wrote this plugin, so I\'m biased.</em></p>\n'}, {'answer_id': 118569, 'author': 'dreeves', 'author_id': 4234, 'author_profile': 'https://Stackoverflow.com/users/4234', 'pm_score': 3, 'selected': False, 'text': '<p>Here\'s the algorithm stackoverflow uses but rewritten more concisely in perlish pseudocode with a bug fix (no "one hours ago").  The function takes a (positive) number of seconds ago and returns a human-friendly string like "3 hours ago" or "yesterday".</p>\n\n<pre><code>agoify($delta)\n  local($y, $mo, $d, $h, $m, $s);\n  $s = floor($delta);\n  if($s&lt;=1)            return "a second ago";\n  if($s&lt;60)            return "$s seconds ago";\n  $m = floor($s/60);\n  if($m==1)            return "a minute ago";\n  if($m&lt;45)            return "$m minutes ago";\n  $h = floor($m/60);\n  if($h==1)            return "an hour ago";\n  if($h&lt;24)            return "$h hours ago";\n  $d = floor($h/24);\n  if($d&lt;2)             return "yesterday";\n  if($d&lt;30)            return "$d days ago";\n  $mo = floor($d/30);\n  if($mo&lt;=1)           return "a month ago";\n  $y = floor($mo/12);\n  if($y&lt;1)             return "$mo months ago";\n  if($y==1)            return "a year ago";\n  return "$y years ago";\n</code></pre>\n'}, {'answer_id': 229285, 'author': 'Jauder Ho', 'author_id': 26366, 'author_profile': 'https://Stackoverflow.com/users/26366', 'pm_score': 5, 'selected': False, 'text': '<p>I would recommend computing this on the client side too. Less work for the server. </p>\n\n<p>The following is the version that I use (from Zach Leatherman)</p>\n\n<pre class="lang-csharp prettyprint-override"><code>/*\n * Javascript Humane Dates\n * Copyright (c) 2008 Dean Landolt (deanlandolt.com)\n * Re-write by Zach Leatherman (zachleat.com)\n * \n * Adopted from the John Resig\'s pretty.js\n * at http://ejohn.org/blog/javascript-pretty-date\n * and henrah\'s proposed modification \n * at http://ejohn.org/blog/javascript-pretty-date/#comment-297458\n * \n * Licensed under the MIT license.\n */\n\nfunction humane_date(date_str){\n        var time_formats = [\n                [60, \'just now\'],\n                [90, \'1 minute\'], // 60*1.5\n                [3600, \'minutes\', 60], // 60*60, 60\n                [5400, \'1 hour\'], // 60*60*1.5\n                [86400, \'hours\', 3600], // 60*60*24, 60*60\n                [129600, \'1 day\'], // 60*60*24*1.5\n                [604800, \'days\', 86400], // 60*60*24*7, 60*60*24\n                [907200, \'1 week\'], // 60*60*24*7*1.5\n                [2628000, \'weeks\', 604800], // 60*60*24*(365/12), 60*60*24*7\n                [3942000, \'1 month\'], // 60*60*24*(365/12)*1.5\n                [31536000, \'months\', 2628000], // 60*60*24*365, 60*60*24*(365/12)\n                [47304000, \'1 year\'], // 60*60*24*365*1.5\n                [3153600000, \'years\', 31536000], // 60*60*24*365*100, 60*60*24*365\n                [4730400000, \'1 century\'] // 60*60*24*365*100*1.5\n        ];\n\n        var time = (\'\' + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),\n                dt = new Date,\n                seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),\n                token = \' ago\',\n                i = 0,\n                format;\n\n        if (seconds &lt; 0) {\n                seconds = Math.abs(seconds);\n                token = \'\';\n        }\n\n        while (format = time_formats[i++]) {\n                if (seconds &lt; format[0]) {\n                        if (format.length == 2) {\n                                return format[1] + (i &gt; 1 ? token : \'\'); // Conditional so we don\'t return Just Now Ago\n                        } else {\n                                return Math.round(seconds / format[2]) + \' \' + format[1] + (i &gt; 1 ? token : \'\');\n                        }\n                }\n        }\n\n        // overflow for centuries\n        if(seconds &gt; 4730400000)\n                return Math.round(seconds / 4730400000) + \' centuries\' + token;\n\n        return date_str;\n};\n\nif(typeof jQuery != \'undefined\') {\n        jQuery.fn.humane_dates = function(){\n                return this.each(function(){\n                        var date = humane_date(this.title);\n                        if(date &amp;&amp; jQuery(this).text() != date) // don\'t modify the dom if we don\'t have to\n                                jQuery(this).text(date);\n                });\n        };\n}\n</code></pre>\n'}, {'answer_id': 501415, 'author': 'Thomaschaaf', 'author_id': 19929, 'author_profile': 'https://Stackoverflow.com/users/19929', 'pm_score': 6, 'selected': False, 'text': '<p>Here a rewrite from Jeffs Script for PHP:</p>\n\n<pre class="lang-php prettyprint-override"><code>define("SECOND", 1);\ndefine("MINUTE", 60 * SECOND);\ndefine("HOUR", 60 * MINUTE);\ndefine("DAY", 24 * HOUR);\ndefine("MONTH", 30 * DAY);\nfunction relativeTime($time)\n{   \n    $delta = time() - $time;\n\n    if ($delta &lt; 1 * MINUTE)\n    {\n        return $delta == 1 ? "one second ago" : $delta . " seconds ago";\n    }\n    if ($delta &lt; 2 * MINUTE)\n    {\n      return "a minute ago";\n    }\n    if ($delta &lt; 45 * MINUTE)\n    {\n        return floor($delta / MINUTE) . " minutes ago";\n    }\n    if ($delta &lt; 90 * MINUTE)\n    {\n      return "an hour ago";\n    }\n    if ($delta &lt; 24 * HOUR)\n    {\n      return floor($delta / HOUR) . " hours ago";\n    }\n    if ($delta &lt; 48 * HOUR)\n    {\n      return "yesterday";\n    }\n    if ($delta &lt; 30 * DAY)\n    {\n        return floor($delta / DAY) . " days ago";\n    }\n    if ($delta &lt; 12 * MONTH)\n    {\n      $months = floor($delta / DAY / 30);\n      return $months &lt;= 1 ? "one month ago" : $months . " months ago";\n    }\n    else\n    {\n        $years = floor($delta / DAY / 365);\n        return $years &lt;= 1 ? "one year ago" : $years . " years ago";\n    }\n}    \n</code></pre>\n'}, {'answer_id': 569913, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 4, 'selected': False, 'text': '<p>Is there an easy way to do this in Java? The <code>java.util.Date</code> class seems rather limited.</p>\n\n<p>Here is my quick and dirty Java solution:</p>\n\n<pre><code>import java.util.Date;\nimport javax.management.timer.Timer;\n\nString getRelativeDate(Date date) {     \n  long delta = new Date().getTime() - date.getTime();\n  if (delta &lt; 1L * Timer.ONE_MINUTE) {\n    return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta) + " seconds ago";\n  }\n  if (delta &lt; 2L * Timer.ONE_MINUTE) {\n    return "a minute ago";\n  }\n  if (delta &lt; 45L * Timer.ONE_MINUTE) {\n    return toMinutes(delta) + " minutes ago";\n  }\n  if (delta &lt; 90L * Timer.ONE_MINUTE) {\n    return "an hour ago";\n  }\n  if (delta &lt; 24L * Timer.ONE_HOUR) {\n    return toHours(delta) + " hours ago";\n  }\n  if (delta &lt; 48L * Timer.ONE_HOUR) {\n    return "yesterday";\n  }\n  if (delta &lt; 30L * Timer.ONE_DAY) {\n    return toDays(delta) + " days ago";\n  }\n  if (delta &lt; 12L * 4L * Timer.ONE_WEEK) { // a month\n    long months = toMonths(delta); \n    return months &lt;= 1 ? "one month ago" : months + " months ago";\n  }\n  else {\n    long years = toYears(delta);\n    return years &lt;= 1 ? "one year ago" : years + " years ago";\n  }\n}\n\nprivate long toSeconds(long date) {\n  return date / 1000L;\n}\n\nprivate long toMinutes(long date) {\n  return toSeconds(date) / 60L;\n}\n\nprivate long toHours(long date) {\n  return toMinutes(date) / 60L;\n}\n\nprivate long toDays(long date) {\n  return toHours(date) / 24L;\n}\n\nprivate long toMonths(long date) {\n  return toDays(date) / 30L;\n}\n\nprivate long toYears(long date) {\n  return toMonths(date) / 365L;\n}\n</code></pre>\n'}, {'answer_id': 628203, 'author': 'neuracnu', 'author_id': 19277, 'author_profile': 'https://Stackoverflow.com/users/19277', 'pm_score': 6, 'selected': False, 'text': '<p>Here\'s an implementation I added as an extension method to the DateTime class that handles both future and past dates and provides an approximation option that allows you to specify the level of detail you\'re looking for ("3 hour ago" vs "3 hours, 23 minutes, 12 seconds ago"):</p>\n\n<pre class="lang-csharp prettyprint-override"><code>using System.Text;\n\n/// &lt;summary&gt;\n/// Compares a supplied date to the current date and generates a friendly English \n/// comparison ("5 days ago", "5 days from now")\n/// &lt;/summary&gt;\n/// &lt;param name="date"&gt;The date to convert&lt;/param&gt;\n/// &lt;param name="approximate"&gt;When off, calculate timespan down to the second.\n/// When on, approximate to the largest round unit of time.&lt;/param&gt;\n/// &lt;returns&gt;&lt;/returns&gt;\npublic static string ToRelativeDateString(this DateTime value, bool approximate)\n{\n    StringBuilder sb = new StringBuilder();\n\n    string suffix = (value &gt; DateTime.Now) ? " from now" : " ago";\n\n    TimeSpan timeSpan = new TimeSpan(Math.Abs(DateTime.Now.Subtract(value).Ticks));\n\n    if (timeSpan.Days &gt; 0)\n    {\n        sb.AppendFormat("{0} {1}", timeSpan.Days,\n          (timeSpan.Days &gt; 1) ? "days" : "day");\n        if (approximate) return sb.ToString() + suffix;\n    }\n    if (timeSpan.Hours &gt; 0)\n    {\n        sb.AppendFormat("{0}{1} {2}", (sb.Length &gt; 0) ? ", " : string.Empty,\n          timeSpan.Hours, (timeSpan.Hours &gt; 1) ? "hours" : "hour");\n        if (approximate) return sb.ToString() + suffix;\n    }\n    if (timeSpan.Minutes &gt; 0)\n    {\n        sb.AppendFormat("{0}{1} {2}", (sb.Length &gt; 0) ? ", " : string.Empty, \n          timeSpan.Minutes, (timeSpan.Minutes &gt; 1) ? "minutes" : "minute");\n        if (approximate) return sb.ToString() + suffix;\n    }\n    if (timeSpan.Seconds &gt; 0)\n    {\n        sb.AppendFormat("{0}{1} {2}", (sb.Length &gt; 0) ? ", " : string.Empty, \n          timeSpan.Seconds, (timeSpan.Seconds &gt; 1) ? "seconds" : "second");\n        if (approximate) return sb.ToString() + suffix;\n    }\n    if (sb.Length == 0) return "right now";\n\n    sb.Append(suffix);\n    return sb.ToString();\n}\n</code></pre>\n'}, {'answer_id': 1141237, 'author': 'Chris Charabaruk', 'author_id': 5697, 'author_profile': 'https://Stackoverflow.com/users/5697', 'pm_score': 4, 'selected': False, 'text': '<pre><code>using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\npublic static class RelativeDateHelper\n{\n    private static Dictionary&lt;double, Func&lt;double, string&gt;&gt; sm_Dict = null;\n\n    private static Dictionary&lt;double, Func&lt;double, string&gt;&gt; DictionarySetup()\n    {\n        var dict = new Dictionary&lt;double, Func&lt;double, string&gt;&gt;();\n        dict.Add(0.75, (mins) =&gt; "less than a minute");\n        dict.Add(1.5, (mins) =&gt; "about a minute");\n        dict.Add(45, (mins) =&gt; string.Format("{0} minutes", Math.Round(mins)));\n        dict.Add(90, (mins) =&gt; "about an hour");\n        dict.Add(1440, (mins) =&gt; string.Format("about {0} hours", Math.Round(Math.Abs(mins / 60)))); // 60 * 24\n        dict.Add(2880, (mins) =&gt; "a day"); // 60 * 48\n        dict.Add(43200, (mins) =&gt; string.Format("{0} days", Math.Floor(Math.Abs(mins / 1440)))); // 60 * 24 * 30\n        dict.Add(86400, (mins) =&gt; "about a month"); // 60 * 24 * 60\n        dict.Add(525600, (mins) =&gt; string.Format("{0} months", Math.Floor(Math.Abs(mins / 43200)))); // 60 * 24 * 365 \n        dict.Add(1051200, (mins) =&gt; "about a year"); // 60 * 24 * 365 * 2\n        dict.Add(double.MaxValue, (mins) =&gt; string.Format("{0} years", Math.Floor(Math.Abs(mins / 525600))));\n\n        return dict;\n    }\n\n    public static string ToRelativeDate(this DateTime input)\n    {\n        TimeSpan oSpan = DateTime.Now.Subtract(input);\n        double TotalMinutes = oSpan.TotalMinutes;\n        string Suffix = " ago";\n\n        if (TotalMinutes &lt; 0.0)\n        {\n            TotalMinutes = Math.Abs(TotalMinutes);\n            Suffix = " from now";\n        }\n\n        if (null == sm_Dict)\n            sm_Dict = DictionarySetup();\n\n        return sm_Dict.First(n =&gt; TotalMinutes &lt; n.Key).Value.Invoke(TotalMinutes) + Suffix;\n    }\n}\n</code></pre>\n\n<p>The same as <a href="https://stackoverflow.com/questions/11/how-do-i-calculate-relative-time/79601#79601">another answer to this question</a> but as an extension method with a static dictionary.</p>\n'}, {'answer_id': 1379178, 'author': 'Simon', 'author_id': 53158, 'author_profile': 'https://Stackoverflow.com/users/53158', 'pm_score': 4, 'selected': False, 'text': '<p>using <a href="https://github.com/FluentDateTime" rel="nofollow noreferrer">Fluent DateTime</a></p>\n\n<pre><code>var dateTime1 = 2.Hours().Ago();\nvar dateTime2 = 3.Days().Ago();\nvar dateTime3 = 1.Months().Ago();\nvar dateTime4 = 5.Hours().FromNow();\nvar dateTime5 = 2.Weeks().FromNow();\nvar dateTime6 = 40.Seconds().FromNow();\n</code></pre>\n'}, {'answer_id': 1735172, 'author': 'antony.trupe', 'author_id': 5849, 'author_profile': 'https://Stackoverflow.com/users/5849', 'pm_score': 3, 'selected': False, 'text': '<p>Java for client-side gwt usage:</p>\n\n<pre><code>import java.util.Date;\n\npublic class RelativeDateFormat {\n\n private static final long ONE_MINUTE = 60000L;\n private static final long ONE_HOUR = 3600000L;\n private static final long ONE_DAY = 86400000L;\n private static final long ONE_WEEK = 604800000L;\n\n public static String format(Date date) {\n\n  long delta = new Date().getTime() - date.getTime();\n  if (delta &lt; 1L * ONE_MINUTE) {\n   return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta)\n     + " seconds ago";\n  }\n  if (delta &lt; 2L * ONE_MINUTE) {\n   return "one minute ago";\n  }\n  if (delta &lt; 45L * ONE_MINUTE) {\n   return toMinutes(delta) + " minutes ago";\n  }\n  if (delta &lt; 90L * ONE_MINUTE) {\n   return "one hour ago";\n  }\n  if (delta &lt; 24L * ONE_HOUR) {\n   return toHours(delta) + " hours ago";\n  }\n  if (delta &lt; 48L * ONE_HOUR) {\n   return "yesterday";\n  }\n  if (delta &lt; 30L * ONE_DAY) {\n   return toDays(delta) + " days ago";\n  }\n  if (delta &lt; 12L * 4L * ONE_WEEK) {\n   long months = toMonths(delta);\n   return months &lt;= 1 ? "one month ago" : months + " months ago";\n  } else {\n   long years = toYears(delta);\n   return years &lt;= 1 ? "one year ago" : years + " years ago";\n  }\n }\n\n private static long toSeconds(long date) {\n  return date / 1000L;\n }\n\n private static long toMinutes(long date) {\n  return toSeconds(date) / 60L;\n }\n\n private static long toHours(long date) {\n  return toMinutes(date) / 60L;\n }\n\n private static long toDays(long date) {\n  return toHours(date) / 24L;\n }\n\n private static long toMonths(long date) {\n  return toDays(date) / 30L;\n }\n\n private static long toYears(long date) {\n  return toMonths(date) / 365L;\n }\n\n}\n</code></pre>\n'}, {'answer_id': 2179589, 'author': 'Buhake Sindi', 'author_id': 251173, 'author_profile': 'https://Stackoverflow.com/users/251173', 'pm_score': 3, 'selected': False, 'text': '<p>I got this answer from one of Bill Gates\' blogs. I need to find it on my browser history and I\'ll give you the link.</p>\n<p>The Javascript code to do the same thing (as requested):</p>\n<pre class="lang-js prettyprint-override"><code>function posted(t) {\n    var now = new Date();\n    var diff = parseInt((now.getTime() - Date.parse(t)) / 1000);\n    if (diff &lt; 60) { return \'less than a minute ago\'; }\n    else if (diff &lt; 120) { return \'about a minute ago\'; }\n    else if (diff &lt; (2700)) { return (parseInt(diff / 60)).toString() + \' minutes ago\'; }\n    else if (diff &lt; (5400)) { return \'about an hour ago\'; }\n    else if (diff &lt; (86400)) { return \'about \' + (parseInt(diff / 3600)).toString() + \' hours ago\'; }\n    else if (diff &lt; (172800)) { return \'1 day ago\'; } \n    else {return (parseInt(diff / 86400)).toString() + \' days ago\'; }\n}\n</code></pre>\n<p>Basically, you work in terms of seconds.</p>\n'}, {'answer_id': 2244324, 'author': '0llie', 'author_id': 229906, 'author_profile': 'https://Stackoverflow.com/users/229906', 'pm_score': 4, 'selected': False, 'text': '<h2>iPhone Objective-C Version</h2>\n\n<pre><code>+ (NSString *)timeAgoString:(NSDate *)date {\n    int delta = -(int)[date timeIntervalSinceNow];\n\n    if (delta &lt; 60)\n    {\n        return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%i seconds ago", delta];\n    }\n    if (delta &lt; 120)\n    {\n        return @"a minute ago";\n    }\n    if (delta &lt; 2700)\n    {\n        return [NSString stringWithFormat:@"%i minutes ago", delta/60];\n    }\n    if (delta &lt; 5400)\n    {\n        return @"an hour ago";\n    }\n    if (delta &lt; 24 * 3600)\n    {\n        return [NSString stringWithFormat:@"%i hours ago", delta/3600];\n    }\n    if (delta &lt; 48 * 3600)\n    {\n        return @"yesterday";\n    }\n    if (delta &lt; 30 * 24 * 3600)\n    {\n        return [NSString stringWithFormat:@"%i days ago", delta/(24*3600)];\n    }\n    if (delta &lt; 12 * 30 * 24 * 3600)\n    {\n        int months = delta/(30*24*3600);\n        return months &lt;= 1 ? @"one month ago" : [NSString stringWithFormat:@"%i months ago", months];\n    }\n    else\n    {\n        int years = delta/(12*30*24*3600);\n        return years &lt;= 1 ? @"one year ago" : [NSString stringWithFormat:@"%i years ago", years];\n    }\n}\n</code></pre>\n'}, {'answer_id': 5427203, 'author': 'Town', 'author_id': 54975, 'author_profile': 'https://Stackoverflow.com/users/54975', 'pm_score': 5, 'selected': False, 'text': '<p>A couple of years late to the party, but I had a requirement to do this for both past and future dates, so I combined <a href="https://stackoverflow.com/questions/11/how-do-i-calculate-relative-time/12#12">Jeff</a>\'s and <a href="https://stackoverflow.com/questions/11/how-do-i-calculate-relative-time/1248#1248">Vincent\'s</a> into this.  It\'s a ternarytastic extravaganza! :)</p>\n\n<pre><code>public static class DateTimeHelper\n    {\n        private const int SECOND = 1;\n        private const int MINUTE = 60 * SECOND;\n        private const int HOUR = 60 * MINUTE;\n        private const int DAY = 24 * HOUR;\n        private const int MONTH = 30 * DAY;\n\n        /// &lt;summary&gt;\n        /// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months".\n        /// &lt;/summary&gt;\n        /// &lt;param name="dateTime"&gt;The DateTime to compare to Now&lt;/param&gt;\n        /// &lt;returns&gt;A friendly string&lt;/returns&gt;\n        public static string GetFriendlyRelativeTime(DateTime dateTime)\n        {\n            if (DateTime.UtcNow.Ticks == dateTime.Ticks)\n            {\n                return "Right now!";\n            }\n\n            bool isFuture = (DateTime.UtcNow.Ticks &lt; dateTime.Ticks);\n            var ts = DateTime.UtcNow.Ticks &lt; dateTime.Ticks ? new TimeSpan(dateTime.Ticks - DateTime.UtcNow.Ticks) : new TimeSpan(DateTime.UtcNow.Ticks - dateTime.Ticks);\n\n            double delta = ts.TotalSeconds;\n\n            if (delta &lt; 1 * MINUTE)\n            {\n                return isFuture ? "in " + (ts.Seconds == 1 ? "one second" : ts.Seconds + " seconds") : ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";\n            }\n            if (delta &lt; 2 * MINUTE)\n            {\n                return isFuture ? "in a minute" : "a minute ago";\n            }\n            if (delta &lt; 45 * MINUTE)\n            {\n                return isFuture ? "in " + ts.Minutes + " minutes" : ts.Minutes + " minutes ago";\n            }\n            if (delta &lt; 90 * MINUTE)\n            {\n                return isFuture ? "in an hour" : "an hour ago";\n            }\n            if (delta &lt; 24 * HOUR)\n            {\n                return isFuture ? "in " + ts.Hours + " hours" : ts.Hours + " hours ago";\n            }\n            if (delta &lt; 48 * HOUR)\n            {\n                return isFuture ? "tomorrow" : "yesterday";\n            }\n            if (delta &lt; 30 * DAY)\n            {\n                return isFuture ? "in " + ts.Days + " days" : ts.Days + " days ago";\n            }\n            if (delta &lt; 12 * MONTH)\n            {\n                int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));\n                return isFuture ? "in " + (months &lt;= 1 ? "one month" : months + " months") : months &lt;= 1 ? "one month ago" : months + " months ago";\n            }\n            else\n            {\n                int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));\n                return isFuture ? "in " + (years &lt;= 1 ? "one year" : years + " years") : years &lt;= 1 ? "one year ago" : years + " years ago";\n            }\n        }\n    }\n</code></pre>\n'}, {'answer_id': 5835905, 'author': 'Owen Blacker', 'author_id': 205245, 'author_profile': 'https://Stackoverflow.com/users/205245', 'pm_score': 4, 'selected': False, 'text': '<p>\nGiven the world and her husband appear to be posting code samples, here is what I wrote a while ago, based on a couple of these answers.</p>\n\n<p>I had a specific need for this code to be localisable. So I have two classes — <code>Grammar</code>, which specifies the localisable terms, and <code>FuzzyDateExtensions</code>, which holds a bunch of extension methods. I had no need to deal with future datetimes, so no attempt is made to handle them with this code.</p>\n\n<p>I\'ve left some of the XMLdoc in the source, but removed most (where they\'d be obvious) for brevity\'s sake. I\'ve also not included every class member here:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public class Grammar\n{\n    /// &lt;summary&gt; Gets or sets the term for "just now". &lt;/summary&gt;\n    public string JustNow { get; set; }\n    /// &lt;summary&gt; Gets or sets the term for "X minutes ago". &lt;/summary&gt;\n    /// &lt;remarks&gt;\n    ///     This is a &lt;see cref="String.Format"/&gt; pattern, where &lt;c&gt;{0}&lt;/c&gt;\n    ///     is the number of minutes.\n    /// &lt;/remarks&gt;\n    public string MinutesAgo { get; set; }\n    public string OneHourAgo { get; set; }\n    public string HoursAgo { get; set; }\n    public string Yesterday { get; set; }\n    public string DaysAgo { get; set; }\n    public string LastMonth { get; set; }\n    public string MonthsAgo { get; set; }\n    public string LastYear { get; set; }\n    public string YearsAgo { get; set; }\n    /// &lt;summary&gt; Gets or sets the term for "ages ago". &lt;/summary&gt;\n    public string AgesAgo { get; set; }\n\n    /// &lt;summary&gt;\n    ///     Gets or sets the threshold beyond which the fuzzy date should be\n    ///     considered "ages ago".\n    /// &lt;/summary&gt;\n    public TimeSpan AgesAgoThreshold { get; set; }\n\n    /// &lt;summary&gt;\n    ///     Initialises a new &lt;see cref="Grammar"/&gt; instance with the\n    ///     specified properties.\n    /// &lt;/summary&gt;\n    private void Initialise(string justNow, string minutesAgo,\n        string oneHourAgo, string hoursAgo, string yesterday, string daysAgo,\n        string lastMonth, string monthsAgo, string lastYear, string yearsAgo,\n        string agesAgo, TimeSpan agesAgoThreshold)\n    { ... }\n}\n</code></pre>\n\n<p>The <code>FuzzyDateString</code> class contains:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public static class FuzzyDateExtensions\n{\n    public static string ToFuzzyDateString(this TimeSpan timespan)\n    {\n        return timespan.ToFuzzyDateString(new Grammar());\n    }\n\n    public static string ToFuzzyDateString(this TimeSpan timespan,\n        Grammar grammar)\n    {\n        return GetFuzzyDateString(timespan, grammar);\n    }\n\n    public static string ToFuzzyDateString(this DateTime datetime)\n    {\n        return (DateTime.Now - datetime).ToFuzzyDateString();\n    }\n\n    public static string ToFuzzyDateString(this DateTime datetime,\n       Grammar grammar)\n    {\n        return (DateTime.Now - datetime).ToFuzzyDateString(grammar);\n    }\n\n\n    private static string GetFuzzyDateString(TimeSpan timespan,\n       Grammar grammar)\n    {\n        timespan = timespan.Duration();\n\n        if (timespan &gt;= grammar.AgesAgoThreshold)\n        {\n            return grammar.AgesAgo;\n        }\n\n        if (timespan &lt; new TimeSpan(0, 2, 0))    // 2 minutes\n        {\n            return grammar.JustNow;\n        }\n\n        if (timespan &lt; new TimeSpan(1, 0, 0))    // 1 hour\n        {\n            return String.Format(grammar.MinutesAgo, timespan.Minutes);\n        }\n\n        if (timespan &lt; new TimeSpan(1, 55, 0))    // 1 hour 55 minutes\n        {\n            return grammar.OneHourAgo;\n        }\n\n        if (timespan &lt; new TimeSpan(12, 0, 0)    // 12 hours\n            &amp;&amp; (DateTime.Now - timespan).IsToday())\n        {\n            return String.Format(grammar.HoursAgo, timespan.RoundedHours());\n        }\n\n        if ((DateTime.Now.AddDays(1) - timespan).IsToday())\n        {\n            return grammar.Yesterday;\n        }\n\n        if (timespan &lt; new TimeSpan(32, 0, 0, 0)    // 32 days\n            &amp;&amp; (DateTime.Now - timespan).IsThisMonth())\n        {\n            return String.Format(grammar.DaysAgo, timespan.RoundedDays());\n        }\n\n        if ((DateTime.Now.AddMonths(1) - timespan).IsThisMonth())\n        {\n            return grammar.LastMonth;\n        }\n\n        if (timespan &lt; new TimeSpan(365, 0, 0, 0, 0)    // 365 days\n            &amp;&amp; (DateTime.Now - timespan).IsThisYear())\n        {\n            return String.Format(grammar.MonthsAgo, timespan.RoundedMonths());\n        }\n\n        if ((DateTime.Now - timespan).AddYears(1).IsThisYear())\n        {\n            return grammar.LastYear;\n        }\n\n        return String.Format(grammar.YearsAgo, timespan.RoundedYears());\n    }\n}\n</code></pre>\n\n<p>One of the key things I wanted to achieve, as well as localisation, was that "today" would only mean "this calendar day", so the <code>IsToday</code>, <code>IsThisMonth</code>, <code>IsThisYear</code> methods look like this:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public static bool IsToday(this DateTime date)\n{\n    return date.DayOfYear == DateTime.Now.DayOfYear &amp;&amp; date.IsThisYear();\n}\n</code></pre>\n\n<p>and the rounding methods are like this (I\'ve included <code>RoundedMonths</code>, as that\'s a bit different):</p>\n\n<pre class="lang-cs prettyprint-override"><code>public static int RoundedDays(this TimeSpan timespan)\n{\n    return (timespan.Hours &gt; 12) ? timespan.Days + 1 : timespan.Days;\n}\n\npublic static int RoundedMonths(this TimeSpan timespan)\n{\n    DateTime then = DateTime.Now - timespan;\n\n    // Number of partial months elapsed since 1 Jan, AD 1 (DateTime.MinValue)\n    int nowMonthYears = DateTime.Now.Year * 12 + DateTime.Now.Month;\n    int thenMonthYears = then.Year * 12 + then.Month;                    \n\n    return nowMonthYears - thenMonthYears;\n}\n</code></pre>\n\n<p>I hope people find this useful and/or interesting  :o)</p>\n'}, {'answer_id': 10775917, 'author': 'JoeyFur62', 'author_id': 1420406, 'author_profile': 'https://Stackoverflow.com/users/1420406', 'pm_score': 3, 'selected': False, 'text': '<pre class="lang-cs prettyprint-override"><code>var ts = new TimeSpan(DateTime.Now.Ticks - dt.Ticks);\n</code></pre>\n'}, {'answer_id': 12406029, 'author': 'tugberk', 'author_id': 463785, 'author_profile': 'https://Stackoverflow.com/users/463785', 'pm_score': 3, 'selected': False, 'text': '<p>I would provide some handy extensions methods for this and make the code more readable. First, couple of extension methods for <code>Int32</code>.</p>\n\n<pre><code>public static class TimeSpanExtensions {\n\n    public static TimeSpan Days(this int value) {\n\n        return new TimeSpan(value, 0, 0, 0);\n    }\n\n    public static TimeSpan Hours(this int value) {\n\n        return new TimeSpan(0, value, 0, 0);\n    }\n\n    public static TimeSpan Minutes(this int value) {\n\n        return new TimeSpan(0, 0, value, 0);\n    }\n\n    public static TimeSpan Seconds(this int value) {\n\n        return new TimeSpan(0, 0, 0, value);\n    }\n\n    public static TimeSpan Milliseconds(this int value) {\n\n        return new TimeSpan(0, 0, 0, 0, value);\n    }\n\n    public static DateTime Ago(this TimeSpan value) {\n\n        return DateTime.Now - value;\n    }\n}\n</code></pre>\n\n<p>Then, one for <code>DateTime</code>.</p>\n\n<pre><code>public static class DateTimeExtensions {\n\n    public static DateTime Ago(this DateTime dateTime, TimeSpan delta) {\n\n        return dateTime - delta;\n    }\n}\n</code></pre>\n\n<p>Now, you can do something like below:</p>\n\n<pre><code>var date = DateTime.Now;\ndate.Ago(2.Days()); // 2 days ago\ndate.Ago(7.Hours()); // 7 hours ago\ndate.Ago(567.Milliseconds()); // 567 milliseconds ago\n</code></pre>\n'}, {'answer_id': 15446338, 'author': 'Prashant Gupta', 'author_id': 985335, 'author_profile': 'https://Stackoverflow.com/users/985335', 'pm_score': 3, 'selected': False, 'text': '<p>I think there is already a number of answers related to this post, but one can use this which is easy to use just like plugin and also easily readable for programmers. \nSend your specific date, and get its value in string form:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public string RelativeDateTimeCount(DateTime inputDateTime)\n{\n    string outputDateTime = string.Empty;\n    TimeSpan ts = DateTime.Now - inputDateTime;\n\n    if (ts.Days &gt; 7)\n    { outputDateTime = inputDateTime.ToString("MMMM d, yyyy"); }\n\n    else if (ts.Days &gt; 0)\n    {\n        outputDateTime = ts.Days == 1 ? ("about 1 Day ago") : ("about " + ts.Days.ToString() + " Days ago");\n    }\n    else if (ts.Hours &gt; 0)\n    {\n        outputDateTime = ts.Hours == 1 ? ("an hour ago") : (ts.Hours.ToString() + " hours ago");\n    }\n    else if (ts.Minutes &gt; 0)\n    {\n        outputDateTime = ts.Minutes == 1 ? ("1 minute ago") : (ts.Minutes.ToString() + " minutes ago");\n    }\n    else outputDateTime = "few seconds ago";\n\n    return outputDateTime;\n}\n</code></pre>\n'}, {'answer_id': 18074585, 'author': 'string.Empty', 'author_id': 2027232, 'author_profile': 'https://Stackoverflow.com/users/2027232', 'pm_score': 2, 'selected': False, 'text': '<pre><code>public string getRelativeDateTime(DateTime date)\n{\n    TimeSpan ts = DateTime.Now - date;\n    if (ts.TotalMinutes &lt; 1)//seconds ago\n        return "just now";\n    if (ts.TotalHours &lt; 1)//min ago\n        return (int)ts.TotalMinutes == 1 ? "1 Minute ago" : (int)ts.TotalMinutes + " Minutes ago";\n    if (ts.TotalDays &lt; 1)//hours ago\n        return (int)ts.TotalHours == 1 ? "1 Hour ago" : (int)ts.TotalHours + " Hours ago";\n    if (ts.TotalDays &lt; 7)//days ago\n        return (int)ts.TotalDays == 1 ? "1 Day ago" : (int)ts.TotalDays + " Days ago";\n    if (ts.TotalDays &lt; 30.4368)//weeks ago\n        return (int)(ts.TotalDays / 7) == 1 ? "1 Week ago" : (int)(ts.TotalDays / 7) + " Weeks ago";\n    if (ts.TotalDays &lt; 365.242)//months ago\n        return (int)(ts.TotalDays / 30.4368) == 1 ? "1 Month ago" : (int)(ts.TotalDays / 30.4368) + " Months ago";\n    //years ago\n    return (int)(ts.TotalDays / 365.242) == 1 ? "1 Year ago" : (int)(ts.TotalDays / 365.242) + " Years ago";\n}\n</code></pre>\n\n<p>Conversion values for days in a month and year were taken from Google.</p>\n'}, {'answer_id': 19377828, 'author': 'Premdeep Mohanty', 'author_id': 2749766, 'author_profile': 'https://Stackoverflow.com/users/2749766', 'pm_score': 4, 'selected': False, 'text': '<p>you can try this.I think it will work correctly.</p>\n\n<pre><code>long delta = new Date().getTime() - date.getTime();\nconst int SECOND = 1;\nconst int MINUTE = 60 * SECOND;\nconst int HOUR = 60 * MINUTE;\nconst int DAY = 24 * HOUR;\nconst int MONTH = 30 * DAY;\n\nif (delta &lt; 0L)\n{\n  return "not yet";\n}\nif (delta &lt; 1L * MINUTE)\n{\n  return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";\n}\nif (delta &lt; 2L * MINUTE)\n{\n  return "a minute ago";\n}\nif (delta &lt; 45L * MINUTE)\n{\n  return ts.Minutes + " minutes ago";\n}\nif (delta &lt; 90L * MINUTE)\n{\n  return "an hour ago";\n}\nif (delta &lt; 24L * HOUR)\n{\n  return ts.Hours + " hours ago";\n}\nif (delta &lt; 48L * HOUR)\n{\n  return "yesterday";\n}\nif (delta &lt; 30L * DAY)\n{\n  return ts.Days + " days ago";\n}\nif (delta &lt; 12L * MONTH)\n{\n  int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));\n  return months &lt;= 1 ? "one month ago" : months + " months ago";\n}\nelse\n{\n  int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));\n  return years &lt;= 1 ? "one year ago" : years + " years ago";\n}\n</code></pre>\n'}, {'answer_id': 22961626, 'author': 'Karl-Henrik', 'author_id': 1770846, 'author_profile': 'https://Stackoverflow.com/users/1770846', 'pm_score': 6, 'selected': False, 'text': '<p>There are also a package called <a href="https://github.com/Humanizr/Humanizer" rel="noreferrer">Humanizr</a> on Nuget, and it actually works really well, and is in the .NET Foundation.</p>\n\n<pre><code>DateTime.UtcNow.AddHours(-30).Humanize() =&gt; "yesterday"\nDateTime.UtcNow.AddHours(-2).Humanize() =&gt; "2 hours ago"\n\nDateTime.UtcNow.AddHours(30).Humanize() =&gt; "tomorrow"\nDateTime.UtcNow.AddHours(2).Humanize() =&gt; "2 hours from now"\n\nTimeSpan.FromMilliseconds(1299630020).Humanize() =&gt; "2 weeks"\nTimeSpan.FromMilliseconds(1299630020).Humanize(3) =&gt; "2 weeks, 1 day, 1 hour"\n</code></pre>\n\n<p>Scott Hanselman has a writeup on it on his <a href="http://www.hanselman.com/blog/NuGetPackageOfTheWeekHumanizerMakesNETDataTypesMoreHuman.aspx" rel="noreferrer">blog</a></p>\n'}, {'answer_id': 25677278, 'author': 'Wai Ho Leung', 'author_id': 1418148, 'author_profile': 'https://Stackoverflow.com/users/1418148', 'pm_score': 2, 'selected': False, 'text': '<pre class="lang-java prettyprint-override"><code>/** \n * {@code date1} has to be earlier than {@code date2}.\n */\npublic static String relativize(Date date1, Date date2) {\n    assert date2.getTime() &gt;= date1.getTime();\n\n    long duration = date2.getTime() - date1.getTime();\n    long converted;\n\n    if ((converted = TimeUnit.MILLISECONDS.toDays(duration)) &gt; 0) {\n        return String.format("%d %s ago", converted, converted == 1 ? "day" : "days");\n    } else if ((converted = TimeUnit.MILLISECONDS.toHours(duration)) &gt; 0) {\n        return String.format("%d %s ago", converted, converted == 1 ? "hour" : "hours");\n    } else if ((converted = TimeUnit.MILLISECONDS.toMinutes(duration)) &gt; 0) {\n        return String.format("%d %s ago", converted, converted == 1 ? "minute" : "minutes");\n    } else if ((converted = TimeUnit.MILLISECONDS.toSeconds(duration)) &gt; 0) {\n        return String.format("%d %s ago", converted, converted == 1 ? "second" : "seconds");\n    } else {\n        return "just now";\n    }\n}\n</code></pre>\n'}, {'answer_id': 32459883, 'author': 'Bgl86', 'author_id': 5293002, 'author_profile': 'https://Stackoverflow.com/users/5293002', 'pm_score': 3, 'selected': False, 'text': '<p>If you want to have an output like <code>"2 days, 4 hours and 12 minutes ago"</code>, you need a timespan:</p>\n\n<pre class="lang-cs prettyprint-override"><code>TimeSpan timeDiff = DateTime.Now-CreatedDate;\n</code></pre>\n\n<p>Then you can access the values you like:</p>\n\n<pre class="lang-cs prettyprint-override"><code>timeDiff.Days\ntimeDiff.Hours\n</code></pre>\n\n<p>etc...</p>\n'}, {'answer_id': 32459892, 'author': 'Piotr Stapp', 'author_id': 1749895, 'author_profile': 'https://Stackoverflow.com/users/1749895', 'pm_score': 4, 'selected': False, 'text': '<p>You can use <a href="http://dotnetthoughts.net/time-ago-function-for-c/" rel="noreferrer">TimeAgo extension</a> as below:</p>\n<pre><code>public static string TimeAgo(this DateTime dateTime)\n{\n    string result = string.Empty;\n    var timeSpan = DateTime.Now.Subtract(dateTime);\n \n    if (timeSpan &lt;= TimeSpan.FromSeconds(60))\n    {\n        result = string.Format(&quot;{0} seconds ago&quot;, timeSpan.Seconds);\n    }\n    else if (timeSpan &lt;= TimeSpan.FromMinutes(60))\n    {\n        result = timeSpan.Minutes &gt; 1 ? \n            String.Format(&quot;about {0} minutes ago&quot;, timeSpan.Minutes) :\n            &quot;about a minute ago&quot;;\n    }\n    else if (timeSpan &lt;= TimeSpan.FromHours(24))\n    {\n        result = timeSpan.Hours &gt; 1 ? \n            String.Format(&quot;about {0} hours ago&quot;, timeSpan.Hours) : \n            &quot;about an hour ago&quot;;\n    }\n    else if (timeSpan &lt;= TimeSpan.FromDays(30))\n    {\n        result = timeSpan.Days &gt; 1 ? \n            String.Format(&quot;about {0} days ago&quot;, timeSpan.Days) : \n            &quot;yesterday&quot;;\n    }\n    else if (timeSpan &lt;= TimeSpan.FromDays(365))\n    {\n        result = timeSpan.Days &gt; 30 ? \n            String.Format(&quot;about {0} months ago&quot;, timeSpan.Days / 30) : \n            &quot;about a month ago&quot;;\n    }\n    else\n    {\n        result = timeSpan.Days &gt; 365 ? \n            String.Format(&quot;about {0} years ago&quot;, timeSpan.Days / 365) : \n            &quot;about a year ago&quot;;\n    }\n \n    return result;\n}\n</code></pre>\n<p>Or use <a href="http://ardalis.com/wiring-up-timeago-and-aspnet-mvc" rel="noreferrer">jQuery plugin</a> with Razor extension from Timeago.</p>\n'}, {'answer_id': 46029235, 'author': 'VnDevil', 'author_id': 1326699, 'author_profile': 'https://Stackoverflow.com/users/1326699', 'pm_score': 1, 'selected': False, 'text': '<p>This is my function, works like a charm :)</p>\n<pre><code>public static string RelativeDate(DateTime theDate)\n{\n   var span = DateTime.Now - theDate;\n   if (span.Days &gt; 365)\n   {\n      var years = (span.Days / 365);\n      if (span.Days % 365 != 0)\n         years += 1;\n      return $&quot;about {years} {(years == 1 ? &quot;year&quot; : &quot;years&quot;)} ago&quot;;\n   }\n   if (span.Days &gt; 30)\n   {\n      var months = (span.Days / 30);\n      if (span.Days % 31 != 0)\n         months += 1;\n      return $&quot;about {months} {(months == 1 ? &quot;month&quot; : &quot;months&quot;)} ago&quot;;\n   }\n   if (span.Days &gt; 0)\n      return $&quot;about {span.Days} {(span.Days == 1 ? &quot;day&quot; : &quot;days&quot;)} ago&quot;;\n   if (span.Hours &gt; 0)\n      return $&quot;about {span.Hours} {(span.Hours == 1 ? &quot;hour&quot; : &quot;hours&quot;)} ago&quot;;\n   if (span.Minutes &gt; 0)\n      return $&quot;about {span.Minutes} {(span.Minutes == 1 ? &quot;minute&quot; : &quot;minutes&quot;)} ago&quot;;\n   if (span.Seconds &gt; 5)\n      return $&quot;about {span.Seconds} seconds ago&quot;;\n\n   return span.Seconds &lt;= 5 ? &quot;about 5 seconds ago&quot; : string.Empty;\n}\n</code></pre>\n'}, {'answer_id': 49300196, 'author': 'Beingnin', 'author_id': 7441056, 'author_profile': 'https://Stackoverflow.com/users/7441056', 'pm_score': -1, 'selected': False, 'text': '<p>My way is much more simpler. You can tweak with the return strings as you want</p>\n\n<pre><code>    public static string TimeLeft(DateTime utcDate)\n    {\n        TimeSpan timeLeft = DateTime.UtcNow - utcDate;\n        string timeLeftString = "";\n        if (timeLeft.Days &gt; 0)\n        {\n            timeLeftString += timeLeft.Days == 1 ? timeLeft.Days + " day" : timeLeft.Days + " days";\n        }\n        else if (timeLeft.Hours &gt; 0)\n        {\n            timeLeftString += timeLeft.Hours == 1 ? timeLeft.Hours + " hour" : timeLeft.Hours + " hours";\n        }\n        else\n        {\n            timeLeftString += timeLeft.Minutes == 1 ? timeLeft.Minutes+" minute" : timeLeft.Minutes + " minutes";\n        }\n        return timeLeftString;\n    }\n</code></pre>\n'}, {'answer_id': 54018412, 'author': 'boyukbas', 'author_id': 1051784, 'author_profile': 'https://Stackoverflow.com/users/1051784', 'pm_score': 2, 'selected': False, 'text': '<p><strong>Turkish</strong> localized version of Vincents answer.</p>\n\n<pre><code>    const int SECOND = 1;\n    const int MINUTE = 60 * SECOND;\n    const int HOUR = 60 * MINUTE;\n    const int DAY = 24 * HOUR;\n    const int MONTH = 30 * DAY;\n\n    var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);\n    double delta = Math.Abs(ts.TotalSeconds);\n\n    if (delta &lt; 1 * MINUTE)\n        return ts.Seconds + " saniye önce";\n\n    if (delta &lt; 45 * MINUTE)\n        return ts.Minutes + " dakika önce";\n\n    if (delta &lt; 24 * HOUR)\n        return ts.Hours + " saat önce";\n\n    if (delta &lt; 48 * HOUR)\n        return "dün";\n\n    if (delta &lt; 30 * DAY)\n        return ts.Days + " gün önce";\n\n    if (delta &lt; 12 * MONTH)\n    {\n        int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));\n        return months + " ay önce";\n    }\n    else\n    {\n        int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));\n        return years + " yıl önce";\n    }\n</code></pre>\n'}, {'answer_id': 56310196, 'author': 'Ahmed Osama', 'author_id': 5514131, 'author_profile': 'https://Stackoverflow.com/users/5514131', 'pm_score': 2, 'selected': False, 'text': '<pre><code>// Calculate total days in current year\nint daysInYear;\n\nfor (var i = 1; i &lt;= 12; i++)\n    daysInYear += DateTime.DaysInMonth(DateTime.Now.Year, i);\n\n// Past date\nDateTime dateToCompare = DateTime.Now.Subtract(TimeSpan.FromMinutes(582));\n\n// Calculate difference between current date and past date\ndouble diff = (DateTime.Now - dateToCompare).TotalMilliseconds;\n\nTimeSpan ts = TimeSpan.FromMilliseconds(diff);\n\nvar years = ts.TotalDays / daysInYear; // Years\nvar months = ts.TotalDays / (daysInYear / (double)12); // Months\nvar weeks = ts.TotalDays / 7; // Weeks\nvar days = ts.TotalDays; // Days\nvar hours = ts.TotalHours; // Hours\nvar minutes = ts.TotalMinutes; // Minutes\nvar seconds = ts.TotalSeconds; // Seconds\n\nif (years &gt;= 1)\n    Console.WriteLine(Math.Round(years, 0) + " year(s) ago");\nelse if (months &gt;= 1)\n    Console.WriteLine(Math.Round(months, 0) + " month(s) ago");\nelse if (weeks &gt;= 1)\n    Console.WriteLine(Math.Round(weeks, 0) + " week(s) ago");\nelse if (days &gt;= 1)\n    Console.WriteLine(Math.Round(days, 0) + " days(s) ago");\nelse if (hours &gt;= 1)\n    Console.WriteLine(Math.Round(hours, 0) + " hour(s) ago");\nelse if (minutes &gt;= 1)\n    Console.WriteLine(Math.Round(minutes, 0) + " minute(s) ago");\nelse if (seconds &gt;= 1)\n    Console.WriteLine(Math.Round(seconds, 0) + " second(s) ago");\n\nConsole.ReadLine();\n</code></pre>\n'}, {'answer_id': 64329743, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>In a way you do your <code>DateTime</code> function over calculating relative time by either seconds to years, try something like this:</p>\n<pre><code>using System;\n\npublic class Program {\n    public static string getRelativeTime(DateTime past) {\n        DateTime now = DateTime.Today;\n        string rt = &quot;&quot;;\n        int time;\n        string statement = &quot;&quot;;\n        if (past.Second &gt;= now.Second) {\n            if (past.Second - now.Second == 1) {\n                rt = &quot;second ago&quot;;\n            }\n            rt = &quot;seconds ago&quot;;\n            time = past.Second - now.Second;\n            statement = &quot;&quot; + time;\n            return (statement + rt);\n        }\n        if (past.Minute &gt;= now.Minute) {\n            if (past.Second - now.Second == 1) {\n                rt = &quot;second ago&quot;;\n            } else {\n                rt = &quot;minutes ago&quot;;\n            }\n            time = past.Minute - now.Minute;\n            statement = &quot;&quot; + time;\n            return (statement + rt);\n        }\n        // This process will go on until years\n    }\n    public static void Main() {\n        DateTime before = new DateTime(1995, 8, 24);\n        string date = getRelativeTime(before);\n        Console.WriteLine(&quot;Windows 95 was {0}.&quot;, date);\n    }\n}\n</code></pre>\n<p>Not exactly working but if you modify and debug it a bit, it will likely do the job.</p>\n'}, {'answer_id': 65238004, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>A &quot;one-liner&quot; using deconstruction and Linq to get &quot;n [biggest unit of time] ago&quot; :</p>\n<pre><code>TimeSpan timeSpan = DateTime.Now - new DateTime(1234, 5, 6, 7, 8, 9);\n\n(string unit, int value) = new Dictionary&lt;string, int&gt;\n{\n    {&quot;year(s)&quot;, (int)(timeSpan.TotalDays / 365.25)}, //https://en.wikipedia.org/wiki/Year#Intercalation\n    {&quot;month(s)&quot;, (int)(timeSpan.TotalDays / 29.53)}, //https://en.wikipedia.org/wiki/Month\n    {&quot;day(s)&quot;, (int)timeSpan.TotalDays},\n    {&quot;hour(s)&quot;, (int)timeSpan.TotalHours},\n    {&quot;minute(s)&quot;, (int)timeSpan.TotalMinutes},\n    {&quot;second(s)&quot;, (int)timeSpan.TotalSeconds},\n    {&quot;millisecond(s)&quot;, (int)timeSpan.TotalMilliseconds}\n}.First(kvp =&gt; kvp.Value &gt; 0);\n\nConsole.WriteLine($&quot;{value} {unit} ago&quot;);\n</code></pre>\n<p>You get <code>786 year(s) ago</code></p>\n<p>With the current year and month, like</p>\n<pre><code>TimeSpan timeSpan = DateTime.Now - new DateTime(2020, 12, 6, 7, 8, 9);\n</code></pre>\n<p>you get <code>4 day(s) ago</code></p>\n<p>With the actual date, like</p>\n<pre><code>TimeSpan timeSpan = DateTime.Now - DateTime.Now.Date;\n</code></pre>\n<p>you get <code>9 hour(s) ago</code></p>\n'}, {'answer_id': 69020909, 'author': 'Shujat Munawar', 'author_id': 7849868, 'author_profile': 'https://Stackoverflow.com/users/7849868', 'pm_score': -1, 'selected': False, 'text': "<p>Simple and 100% working solution.</p>\n<p>Handling ago and future times as well.. just in case</p>\n<pre><code>        public string GetTimeSince(DateTime postDate)\n    {\n        string message = &quot;&quot;;\n        DateTime currentDate = DateTime.Now;\n        TimeSpan timegap = currentDate - postDate;\n\n     \n        if (timegap.Days &gt; 365)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Years&quot;), (((timegap.Days) / 30) / 12));                \n        }\n        else if (timegap.Days &gt; 30)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Months&quot;), timegap.Days/30);                \n        }\n        else if (timegap.Days &gt; 0)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Days&quot;), timegap.Days);\n        }           \n        else if (timegap.Hours &gt; 0)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Hours&quot;), timegap.Hours);\n        }           \n        else if (timegap.Minutes &gt; 0)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Minutes&quot;), timegap.Minutes);\n        }\n        else if (timegap.Seconds &gt; 0)\n        {\n            message = string.Format(L(&quot;Ago&quot;) + &quot; {0} &quot; + L(&quot;Seconds&quot;), timegap.Seconds);\n        }\n\n        // let's handle future times..just in case       \n        else if (timegap.Days &lt; -365)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Years&quot;), (((Math.Abs(timegap.Days)) / 30) / 12));                \n        }\n        else if (timegap.Days &lt; -30)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Months&quot;), ((Math.Abs(timegap.Days)) / 30));                \n        }\n        else if (timegap.Days &lt; 0)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Days&quot;), Math.Abs(timegap.Days));                \n        }           \n      \n        else if (timegap.Hours &lt; 0)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Hours&quot;), Math.Abs(timegap.Hours));                \n        }\n        else if (timegap.Minutes &lt; 0)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Minutes&quot;), Math.Abs(timegap.Minutes));                \n        }\n        else if (timegap.Seconds &lt; 0)\n        {\n            message = string.Format(L(&quot;In&quot;) + &quot; {0} &quot; + L(&quot;Seconds&quot;), Math.Abs(timegap.Seconds));                \n        }\n\n\n        else\n        {\n            message = &quot;a bit&quot;;\n        }\n\n        return message;\n    }\n</code></pre>\n"}, {'answer_id': 73608368, 'author': 'StudioLE', 'author_id': 247218, 'author_profile': 'https://Stackoverflow.com/users/247218', 'pm_score': 0, 'selected': False, 'text': '<p>The accepted answer by Vincent makes quite a few arbitrary decisions.\nWhy is 45 minutes rounded up to an hour while 45 seconds is not rounded up to a minute?\nIt has an increased level of cyclomatic complexity within the years and month calculations that makes it more complex to follow the logic.\nIt makes the assumption that the TimeSpan is relative to the past (2 days ago) when it could very well be in the future (2 days until).\nIt defines unnecessary constants instead of using <code>TimeSpan.TicksPerSecond</code> etc.</p>\n<p>This implementation resolves the above and updates the syntax to use <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression" rel="nofollow noreferrer">switch expressions</a> and <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#relational-patterns" rel="nofollow noreferrer">relational patterns</a></p>\n<pre class="lang-cs prettyprint-override"><code>/// &lt;summary&gt;\n/// Convert a &lt;see cref=&quot;TimeSpan&quot;/&gt; to a natural language representation.\n/// &lt;/summary&gt;\n/// &lt;example&gt;\n/// &lt;code&gt;\n/// TimeSpan.FromSeconds(10).ToNaturalLanguage();\n/// // 10 seconds\n/// &lt;/code&gt;\n/// &lt;/example&gt;\npublic static string ToNaturalLanguage(this TimeSpan @this)\n{\n    const int daysInWeek = 7;\n    const int daysInMonth = 30;\n    const int daysInYear = 365;\n    const long threshold = 100 * TimeSpan.TicksPerMillisecond;\n    @this = @this.TotalSeconds &lt; 0\n        ? TimeSpan.FromSeconds(@this.TotalSeconds * -1)\n        : @this;\n    return (@this.Ticks + threshold) switch\n    {\n        &lt; 2 * TimeSpan.TicksPerSecond =&gt; &quot;a second&quot;,\n        &lt; 1 * TimeSpan.TicksPerMinute =&gt; @this.Seconds + &quot; seconds&quot;,\n        &lt; 2 * TimeSpan.TicksPerMinute =&gt; &quot;a minute&quot;,\n        &lt; 1 * TimeSpan.TicksPerHour =&gt; @this.Minutes + &quot; minutes&quot;,\n        &lt; 2 * TimeSpan.TicksPerHour =&gt; &quot;an hour&quot;,\n        &lt; 1 * TimeSpan.TicksPerDay =&gt; @this.Hours + &quot; hours&quot;,\n        &lt; 2 * TimeSpan.TicksPerDay =&gt; &quot;a day&quot;,\n        &lt; 1 * daysInWeek * TimeSpan.TicksPerDay =&gt; @this.Days + &quot; days&quot;,\n        &lt; 2 * daysInWeek * TimeSpan.TicksPerDay =&gt; &quot;a week&quot;,\n        &lt; 1 * daysInMonth * TimeSpan.TicksPerDay =&gt; (@this.Days / daysInWeek).ToString(&quot;F0&quot;) + &quot; weeks&quot;,\n        &lt; 2 * daysInMonth * TimeSpan.TicksPerDay =&gt; &quot;a month&quot;,\n        &lt; 1 * daysInYear * TimeSpan.TicksPerDay =&gt; (@this.Days / daysInMonth).ToString(&quot;F0&quot;) + &quot; months&quot;,\n        &lt; 2 * daysInYear * TimeSpan.TicksPerDay =&gt; &quot;a year&quot;,\n        _ =&gt; (@this.Days / daysInYear).ToString(&quot;F0&quot;) + &quot; years&quot;\n    };\n}\n\n/// &lt;summary&gt;\n/// Convert a &lt;see cref=&quot;DateTime&quot;/&gt; to a natural language representation.\n/// &lt;/summary&gt;\n/// &lt;example&gt;\n/// &lt;code&gt;\n/// (DateTime.Now - TimeSpan.FromSeconds(10)).ToNaturalLanguage()\n/// // 10 seconds ago\n/// &lt;/code&gt;\n/// &lt;/example&gt;\npublic static string ToNaturalLanguage(this DateTime @this)\n{\n    TimeSpan timeSpan = @this - DateTime.Now;\n    return timeSpan.TotalSeconds switch\n    {\n        &gt;= 1 =&gt; timeSpan.ToNaturalLanguage() + &quot; until&quot;,\n        &lt;= -1 =&gt; timeSpan.ToNaturalLanguage() + &quot; ago&quot;,\n        _ =&gt; &quot;now&quot;,\n    };\n}\n</code></pre>\n<p>You can test it with NUnit as follows:</p>\n<pre class="lang-cs prettyprint-override"><code>[TestCase(&quot;a second&quot;, 0)]\n[TestCase(&quot;a second&quot;, 1)]\n[TestCase(&quot;2 seconds&quot;, 2)]\n[TestCase(&quot;a minute&quot;, 0, 1)]\n[TestCase(&quot;5 minutes&quot;, 0, 5)]\n[TestCase(&quot;an hour&quot;, 0, 0, 1)]\n[TestCase(&quot;2 hours&quot;, 0, 0, 2)]\n[TestCase(&quot;a day&quot;, 0, 0, 24)]\n[TestCase(&quot;a day&quot;, 0, 0, 0, 1)]\n[TestCase(&quot;6 days&quot;, 0, 0, 0, 6)]\n[TestCase(&quot;a week&quot;, 0, 0, 0, 7)]\n[TestCase(&quot;4 weeks&quot;, 0, 0, 0, 29)]\n[TestCase(&quot;a month&quot;, 0, 0, 0, 30)]\n[TestCase(&quot;6 months&quot;, 0, 0, 0, 6 * 30)]\n[TestCase(&quot;a year&quot;, 0, 0, 0, 365)]\n[TestCase(&quot;68 years&quot;, int.MaxValue)]\npublic void NaturalLanguageHelpers_TimeSpan(\n    string expected,\n    int seconds,\n    int minutes = 0,\n    int hours = 0,\n    int days = 0\n)\n{\n    // Arrange\n    TimeSpan timeSpan = new(days, hours, minutes, seconds);\n\n    // Act\n    string result = timeSpan.ToNaturalLanguage();\n\n    // Assert\n    Assert.That(result, Is.EqualTo(expected));\n}\n\n[TestCase(&quot;now&quot;, 0)]\n[TestCase(&quot;10 minutes ago&quot;, 0, -10)]\n[TestCase(&quot;10 minutes until&quot;, 10, 10)]\n[TestCase(&quot;68 years until&quot;, int.MaxValue)]\n[TestCase(&quot;68 years ago&quot;, int.MinValue)]\npublic void NaturalLanguageHelpers_DateTime(\n    string expected,\n    int seconds,\n    int minutes = 0,\n    int hours = 0,\n    int days = 0\n)\n{\n    // Arrange\n    TimeSpan timeSpan = new(days, hours, minutes, seconds);\n    DateTime now = DateTime.Now;\n    DateTime dateTime = now + timeSpan;\n\n    // Act\n    string result = dateTime.ToNaturalLanguage();\n\n    // Assert\n    Assert.That(result, Is.EqualTo(expected));\n}\n</code></pre>\n<p>Or as a gist: <a href="https://gist.github.com/StudioLE/2dd394e3f792e79adc927ede274df56e" rel="nofollow noreferrer">https://gist.github.com/StudioLE/2dd394e3f792e79adc927ede274df56e</a></p>\n'}]
['https://Stackoverflow.com/questions/11', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1/']