I have a class with 2 date properties: FirstDay
and LastDay
. LastDay
is nullable. I would like to generate a string in the format of "x year(s) y day(s)"
. If the total years are less than 1, I would like to omit the year section. If the total days are less than 1, I would like to omit the day section. If either years or days are 0, they should say "day/year", rather than "days/years" respectively.
Examples:
2.2 years: "2 years 73 days"
1.002738 years: "1 year 1 day"
0.2 years: "73 days"
2 years: "2 years"
What I have works, but it is long:
private const decimal DaysInAYear = 365.242M;
public string LengthInYearsAndDays
{
get
{
var lastDay = this.LastDay ?? DateTime.Today;
var lengthValue = lastDay - this.FirstDay;
var builder = new StringBuilder();
var totalDays = (decimal)lengthValue.TotalDays;
var totalYears = totalDays / DaysInAYear;
var years = (int)Math.Floor(totalYears);
totalDays -= (years * DaysInAYear);
var days = (int)Math.Floor(totalDays);
Func<int, string> sIfPlural = value =>
value > 1 ? "s" : string.Empty;
if (years > 0)
{
builder.AppendFormat(
CultureInfo.InvariantCulture,
"{0} year{1}",
years,
sIfPlural(years));
if (days > 0)
{
builder.Append(" ");
}
}
if (days > 0)
{
builder.AppendFormat(
CultureInfo.InvariantCulture,
"{0} day{1}",
days,
sIfPlural(days));
}
var length = builder.ToString();
return length;
}
}
Is there a more concise way of doing this (but still readable)?
I think this should work:
A
TimeSpan
doesn't have a sensible concept of "years" because it depends on the start and end point. (Months is similar - how many months are there in 29 days? Well, it depends...)To give a shameless plug, my Noda Time project makes this really simple though:
Output:
I wouldn't do this with a
TimeSpan
. Date math gets tricky as soon as you go beyond days because the number of days in a month and days in a year is no longer constant. It's likely whyTimeSpan
does not contain properties forYears
andMonths
. I would instead determine the number of years/months/days, etc between the twoDateTime
values and display the results accordingly.