patterncsharpMinor
Get Elapsed Time as Human Friendly String
Viewed 0 times
elapsedhumantimegetstringfriendly
Problem
In lieu with several other Facebook-esque concepts I am trying to replicate, this working code will take the span of time from a given date to now, and try to convert it into the most convenient English-friendly word. For example, if I post a comment on an article or status, and I want to show when it was posted to a user who views it, it would indicate something like "5 minutes ago", versus a date itself.
Concerns: Does this cover all possible use cases? Is it done optimally in the least lines of code?
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Schloss.Text
{
public static class Date
{
public static string GetElapsedTime(DateTimeOffset datetime)
{
TimeSpan ts = DateTimeOffset.Now.Subtract(datetime);
int years = ts.Days / 365;
int months = ts.Days / 30;
int weeks = ts.Days / 52;
if (years == 1) // one year ago
return "A year ago";
if (years > 1) // greater than one year
{
if (ts.Days % 365 == 0) // even year
return (int)(ts.TotalDays / 365) + " years ago";
else // not really entire years
return "About " + (int)(ts.TotalDays / 365) + " years ago";
}
if (months == 1) // one month
return "About a month ago";
if (months > 1) // more than one month
return "About " + months + " months ago";
if (weeks == 1) // a week ago
return "About a week ago";
if (weeks > 1) // more than a week ago, but less than a month ago
return "About " + weeks + " weeks ago";
if (ts.Days == 1) // one day ago
return "Yesterday";
if (ts.Days > 1) // more than one day ago, but less than one week ago
return ts.Days + " days ago";
Concerns: Does this cover all possible use cases? Is it done optimally in the least lines of code?
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Schloss.Text
{
public static class Date
{
public static string GetElapsedTime(DateTimeOffset datetime)
{
TimeSpan ts = DateTimeOffset.Now.Subtract(datetime);
int years = ts.Days / 365;
int months = ts.Days / 30;
int weeks = ts.Days / 52;
if (years == 1) // one year ago
return "A year ago";
if (years > 1) // greater than one year
{
if (ts.Days % 365 == 0) // even year
return (int)(ts.TotalDays / 365) + " years ago";
else // not really entire years
return "About " + (int)(ts.TotalDays / 365) + " years ago";
}
if (months == 1) // one month
return "About a month ago";
if (months > 1) // more than one month
return "About " + months + " months ago";
if (weeks == 1) // a week ago
return "About a week ago";
if (weeks > 1) // more than a week ago, but less than a month ago
return "About " + weeks + " weeks ago";
if (ts.Days == 1) // one day ago
return "Yesterday";
if (ts.Days > 1) // more than one day ago, but less than one week ago
return ts.Days + " days ago";
Solution
Does this cover all possible use cases?
Maybe, but it doesn't calculate timespan components (year, month, etc) exactly.
Is it done optimally in the least lines of code?
Probably no.
You could generalize check of different
Maybe, but it doesn't calculate timespan components (year, month, etc) exactly.
Is it done optimally in the least lines of code?
Probably no.
You could generalize check of different
TimeSpan elements using the following approach:private static string GetElapsedTime(DateTime datetime)
{
TimeSpan ts = DateTime.Now.Subtract(datetime);
// The trick: make variable contain date and time representing the desired timespan,
// having +1 in each date component.
DateTime date = DateTime.MinValue + ts;
return ProcessPeriod(date.Year - 1, date.Month - 1, "year")
?? ProcessPeriod(date.Month - 1, date.Day - 1, "month")
?? ProcessPeriod(date.Day - 1, date.Hour, "day", "Yesterday")
?? ProcessPeriod(date.Hour, date.Minute, "hour")
?? ProcessPeriod(date.Minute, date.Second, "minute")
?? ProcessPeriod(date.Second, 0, "second")
?? "Right now";
}
private static string ProcessPeriod(int value, int subValue, string name, string singularName = null)
{
if (value == 0)
{
return null;
}
if (value == 1)
{
if (!String.IsNullOrEmpty(singularName))
{
return singularName;
}
string articleSuffix = name[0] == 'h' ? "n" : String.Empty;
return subValue == 0
? String.Format("A{0} {1} ago", articleSuffix, name)
: String.Format("About a{0} {1} ago", articleSuffix, name);
}
return subValue == 0
? String.Format("{0} {1}s ago", value, name)
: String.Format("About {0} {1}s ago", value, name);
}Code Snippets
private static string GetElapsedTime(DateTime datetime)
{
TimeSpan ts = DateTime.Now.Subtract(datetime);
// The trick: make variable contain date and time representing the desired timespan,
// having +1 in each date component.
DateTime date = DateTime.MinValue + ts;
return ProcessPeriod(date.Year - 1, date.Month - 1, "year")
?? ProcessPeriod(date.Month - 1, date.Day - 1, "month")
?? ProcessPeriod(date.Day - 1, date.Hour, "day", "Yesterday")
?? ProcessPeriod(date.Hour, date.Minute, "hour")
?? ProcessPeriod(date.Minute, date.Second, "minute")
?? ProcessPeriod(date.Second, 0, "second")
?? "Right now";
}
private static string ProcessPeriod(int value, int subValue, string name, string singularName = null)
{
if (value == 0)
{
return null;
}
if (value == 1)
{
if (!String.IsNullOrEmpty(singularName))
{
return singularName;
}
string articleSuffix = name[0] == 'h' ? "n" : String.Empty;
return subValue == 0
? String.Format("A{0} {1} ago", articleSuffix, name)
: String.Format("About a{0} {1} ago", articleSuffix, name);
}
return subValue == 0
? String.Format("{0} {1}s ago", value, name)
: String.Format("About {0} {1}s ago", value, name);
}Context
StackExchange Code Review Q#93239, answer score: 4
Revisions (0)
No revisions yet.