There’s a response in the OS And it was accepted. I would probably improve something to look more elegant and still not doing exactly as you wish, but this is it:
public static String RelativeTime(this TimeSpan ts) {
const int second = 1;
const int minute = 60 * second;
const int hour = 60 * minute;
const int day = 24 * hour;
const int month = 30 * day;
double delta = Math.Abs(ts.TotalSeconds);
//melhor se escrever só "Agora há pouco"
if (delta < 1 * minute) return "Há " + (ts.Seconds == 1 ? "um segundo" : ts.Seconds + " segundos");
if (delta < 2 * minute) return "Há um minuto";
if (delta < 45 * minute) return "Há " + ts.Minutes + " minutos";
if (delta < 90 * minute) return "Há uma hora";
if (delta < 24 * hour) return "Há " + ts.Hours + " horas";
if (delta < 48 * hour) return "ontem";
if (delta < 30 * day) return "Há " + ts.Days + " dias";
if (delta < 12 * month) {
var months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return "Há " + (months <= 1 ? "um mês" : months + " meses");
} else {
var years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return "Há " + (years <= 1 ? "um ano" : years + " anos");
}
}
Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.
It has some problems but solves most situations. One of the problems is that it doesn’t deal with whether the value is future. The rounding calibration is rigid, finally, can make several improvements in the algorithm, as well as improve the style of the code.
There’s also this package that helps to "humanize" all this data.
There is an alternative that considers part-time as shown in the question. The implementation does not take into account some small displacements, plural, hours, etc., as reported in original response in the OS:
var dtNow = DateTime.Now;
var dtYesterday = DateTime.Now.AddDays(-435.0);
var ts = dtNow.Subtract(dtYesterday);
var years = ts.Days / 365; //no leap year accounting
var months = (ts.Days % 365) / 30; //naive guess at month size
var weeks = ((ts.Days % 365) % 30) / 7;
var days = (((ts.Days % 365) % 30) % 7);
var sb = new StringBuilder("Há ");
if(years > 0) sb.Append(years.ToString() + " anos, ");
if(months > 0) sb.Append(months.ToString() + " meses, ");
if(weeks > 0) sb.Append(weeks.ToString() + " semanas, ");
if(days > 0) sb.Append(days.ToString() + " dias.");
var FormattedTimeSpan = sb.ToString();
I put in the Github for future reference.
The feature you are looking for is called relative time. This is a starting point.
– dcastro
If you need to support other languages, you can think about this Nuget: Timeago
– Tobias Mesquita
@Sensational Tobymosque this Timeago! I will do some tests with it.
– Leonel Sanches da Silva