views:

1428

answers:

7

Duplicate: This is one of the earliest question on StackOverflow posted by Jeff.

http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time


Does anyone know of a good library (or code snippet) for converting a TimeSpan object to a "friendly" string such as:

  • Two years, three months and four days
  • One week and two days

(It's for a document expiry system, where the expiry could be anything from a few days to several decades)

Just to clarify, say I had a TimeSpan with 7 days, that should print "1 week", 14 days "2 weeks", 366 days "1 year and 1 day", etc etc.

+1  A: 

It probably won't do everything you are looking for, but in v4 Microsoft will be implementing IFormattable on TimeSpan.

Doug McClean
great to know. here's the MSDN page for .NET 4 http://msdn.microsoft.com/en-us/library/dd992632(VS.100).aspx
Simon_Weaver
+2  A: 

The TimeSpan object has Days, Hours, Minutes, and Seconds properties on it, so it wouldn't be too hard to make a snippet that formats those values to a friendly string.

Unfortunately Days is the largest value. Anything longer than that and you'll have to start worrying about days in a month for every year...etc. You're better off stopping at days in my opinion (the added effort doesn't seem worth the gain).

UPDATE

...I figured I'd bring this up from my own comment:

Understandable, but is "This document expires in 10 years, 3 months, 21 days, 2 hours, and 30 minutes" really any more helpful or less silly? If it were up to me, since neither representation seems very useful...

I'd leave off the timespan for expiry until the date got reasonably close (30 or 60 days maybe if you're worried about getting the document updated).

Seems a much better UX choice to me.

Justin Niessner
Days is fine for saying "This document expires in 7 days", but when it's "This document expires in 3892 days" then that looks a bit silly (and unhelpful). I can see how I'd use modulo to do this, but I'm lazy and don't want to spend time re-inventing the wheel :)
Keith Williams
Understandable, but is "This document expires in 10 years, 3 months, 21 days, 2 hours, and 30 minutes" really any more helpful or less silly?If it were up to me, since neither representation seems very useful...I'd leave off the timespan for expiry until the date got reasonably close (30 or 60 days maybe if you're worried about getting the document updated).Seems a much better UX choice to me.
Justin Niessner
A: 

To format any period longer than 1 day (i.e. month/year/decade etc.) a Timespan object is not enough.

Suppose your timespan is 35 days, then from Apr 1 you would get one month and five days, whereas from Dec 1 you would get one month and four days.

Patrick McDonald
A: 

There is the Time Span Articulator:
http://weblog.cynosura.eu/post/2009/01/27/The-TimeSpan-Articulator.aspx

This link will get you numbers to english:

Converting an integer into English Words using C#.Net
http://www.hotblue.com/article0001.aspx

Robert Harvey
+4  A: 

Not a fully featured implementation, but it should get you close enough.

DateTime dtNow = DateTime.Now;
DateTime dtYesterday = DateTime.Now.AddDays(-435.0);
TimeSpan ts = dtNow.Subtract(dtYesterday);

int years = ts.Days / 365; //no leap year accounting
int months = (ts.Days % 365) / 30; //naive guess at month size
int weeks = ((ts.Days % 365) % 30) / 7;
int days = (((ts.Days % 365) % 30) % 7);

StringBuilder sb = new StringBuilder();
if(years > 0)
{
    sb.Append(years.ToString() + " years, ");
}
if(months > 0)
{
    sb.Append(months.ToString() + " months, ");
}
if(weeks > 0)
{
    sb.Append(weeks.ToString() + " weeks, ");
}
if(days > 0)
{
    sb.Append(days.ToString() + " days.");
}
string FormattedTimeSpan = sb.ToString();

In the end, do you really need to let someone know a document is going to expire exactly 1 year, 5 months, 2 weeks, and 3 days from now? Can't you get by with telling them the document will expire over 1 year from now, or over 5 months from now? Just take the largest unit and say over n of that unit.

Andy_Vulhop
Smashing! Cheers for that. Yeah, I think you're right about making the value a bit fuzzier, but it's one of those things where I'll need to test it on a variety of values and see what works out as a sensible middle-ground between too little and too much detail.
Keith Williams
Thanks Patrick McDonald. I totally missed my copy paste error.
Andy_Vulhop
A: 

See how-do-i-calculate-relative-time, asked (by user number 1) a year ago when SO was young and not public. It was (probably) the basis for the current age display for SO questions and answers.

gimel
+1  A: 

This is one of the earliest question on StackOverflow posted by Jeff.

http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time

There are alot of great answers there.

Nick Berardi
Cheers Nick, exactly what I was looking for!
Keith Williams