datetime - Calculate relative time in C#

ID : 679

viewed : 349

Tags : c#datetimedatediffrelative-time-spanc#





Top 5 Answer for datetime - Calculate relative time in C#

vote vote

92

Jeff, your code is nice but could be clearer with constants (as suggested in Code Complete).

const int SECOND = 1; const int MINUTE = 60 * SECOND; const int HOUR = 60 * MINUTE; const int DAY = 24 * HOUR; const int MONTH = 30 * DAY;  var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks); double delta = Math.Abs(ts.TotalSeconds);  if (delta < 1 * MINUTE)   return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";  if (delta < 2 * MINUTE)   return "a minute ago";  if (delta < 45 * MINUTE)   return ts.Minutes + " minutes ago";  if (delta < 90 * MINUTE)   return "an hour ago";  if (delta < 24 * HOUR)   return ts.Hours + " hours ago";  if (delta < 48 * HOUR)   return "yesterday";  if (delta < 30 * DAY)   return ts.Days + " days ago";  if (delta < 12 * MONTH) {   int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));   return months <= 1 ? "one month ago" : months + " months ago"; } else {   int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));   return years <= 1 ? "one year ago" : years + " years ago"; } 
vote vote

84

jquery.timeago plugin

Jeff, because Stack Overflow uses jQuery extensively, I recommend the jquery.timeago plugin.

Benefits:

  • Avoid timestamps dated "1 minute ago" even though the page was opened 10 minutes ago; timeago refreshes automatically.
  • You can take full advantage of page and/or fragment caching in your web applications, because the timestamps aren't calculated on the server.
  • You get to use microformats like the cool kids.

Just attach it to your timestamps on DOM ready:

jQuery(document).ready(function() {     jQuery('abbr.timeago').timeago(); }); 

This will turn all abbr elements with a class of timeago and an ISO 8601 timestamp in the title:

<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr> 

into something like this:

<abbr class="timeago" title="July 17, 2008">4 months ago</abbr> 

which yields: 4 months ago. As time passes, the timestamps will automatically update.

Disclaimer: I wrote this plugin, so I'm biased.

vote vote

72

Here's how I do it

var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks); double delta = Math.Abs(ts.TotalSeconds);  if (delta < 60) {   return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago"; } if (delta < 60 * 2) {   return "a minute ago"; } if (delta < 45 * 60) {   return ts.Minutes + " minutes ago"; } if (delta < 90 * 60) {   return "an hour ago"; } if (delta < 24 * 60 * 60) {   return ts.Hours + " hours ago"; } if (delta < 48 * 60 * 60) {   return "yesterday"; } if (delta < 30 * 24 * 60 * 60) {   return ts.Days + " days ago"; } if (delta < 12 * 30 * 24 * 60 * 60) {   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"; 

Suggestions? Comments? Ways to improve this algorithm?

vote vote

66

public static string RelativeDate(DateTime theDate) {     Dictionary<long, string> thresholds = new Dictionary<long, string>();     int minute = 60;     int hour = 60 * minute;     int day = 24 * hour;     thresholds.Add(60, "{0} seconds ago");     thresholds.Add(minute * 2, "a minute ago");     thresholds.Add(45 * minute, "{0} minutes ago");     thresholds.Add(120 * minute, "an hour ago");     thresholds.Add(day, "{0} hours ago");     thresholds.Add(day * 2, "yesterday");     thresholds.Add(day * 30, "{0} days ago");     thresholds.Add(day * 365, "{0} months ago");     thresholds.Add(long.MaxValue, "{0} years ago");     long since = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;     foreach (long threshold in thresholds.Keys)      {         if (since < threshold)          {             TimeSpan t = new TimeSpan((DateTime.Now.Ticks - theDate.Ticks));             return string.Format(thresholds[threshold], (t.Days > 365 ? t.Days / 365 : (t.Days > 0 ? t.Days : (t.Hours > 0 ? t.Hours : (t.Minutes > 0 ? t.Minutes : (t.Seconds > 0 ? t.Seconds : 0))))).ToString());         }     }     return ""; } 

I prefer this version for its conciseness, and ability to add in new tick points. This could be encapsulated with a Latest() extension to Timespan instead of that long 1 liner, but for the sake of brevity in posting, this will do. This fixes the an hour ago, 1 hours ago, by providing an hour until 2 hours have elapsed

vote vote

60

Here a rewrite from Jeffs Script for PHP:

define("SECOND", 1); define("MINUTE", 60 * SECOND); define("HOUR", 60 * MINUTE); define("DAY", 24 * HOUR); define("MONTH", 30 * DAY); function relativeTime($time) {        $delta = time() - $time;      if ($delta < 1 * MINUTE)     {         return $delta == 1 ? "one second ago" : $delta . " seconds ago";     }     if ($delta < 2 * MINUTE)     {       return "a minute ago";     }     if ($delta < 45 * MINUTE)     {         return floor($delta / MINUTE) . " minutes ago";     }     if ($delta < 90 * MINUTE)     {       return "an hour ago";     }     if ($delta < 24 * HOUR)     {       return floor($delta / HOUR) . " hours ago";     }     if ($delta < 48 * HOUR)     {       return "yesterday";     }     if ($delta < 30 * DAY)     {         return floor($delta / DAY) . " days ago";     }     if ($delta < 12 * MONTH)     {       $months = floor($delta / DAY / 30);       return $months <= 1 ? "one month ago" : $months . " months ago";     }     else     {         $years = floor($delta / DAY / 365);         return $years <= 1 ? "one year ago" : $years . " years ago";     } }     

Top 3 video Explaining datetime - Calculate relative time in C#







Related QUESTION?