I'm currently building a webservice and my client has asked me to return the time remaining until a particular date. I'm able to calculate the number of days remaining, but ideally instead of having 473 days for example, I would be able to show something
like '1 year 4 months and 12 days'

DateTime.TryParse(StartDate.ToShortDateString(), out oldDate);

In your example, the above line does nothing (it converts a datetime to a string and then back to a datetime). If you were trying to strip the time component from a DateTime this is the way to do it:

You could add the days to a known base date and then extract the components and subtract the base. Like this

var baseDate = new DateTime(1,1,1);
var end = baseDate.AddDays(473);
Console.Write("{0} years, {1} months and {2} days",
end.Year - baseDate.Year,
end.Month - baseDate.Month,
end.Day - baseDate.Day);

You will get different results depending on which base year you use because of leap years (as noted above). For example, if you have 59 days and a base of 1/1/1 you get 2 months and 0 days, for a base date of 1/1/2000 you get 1 months and 28 days. Take your
pick.

int numberOfDays = 473;
DateTime date = new DateTime(new TimeSpan(numberOfDays, 0, 0, 0).Ticks);
string dateUntil = string.Format("{0} year(s), {1} month(s) and {2} day(s)", date.Year-1, date.Month-1, date.Day-1);

The -1 for the year, month and day in the string.Format is needed because, well, we start in the year 1 month 1 and day 1 so if numberOfDays = 1 we are in year 1, month 1 and day 2.

Good luck!

And mark the post answered if this works for you ;)

Using the timespan has limitations as it doesnt do months and years. Even the Scott Mitchell acticle stops with Days as it used a timespan.

Paul's method was nice and concise and looked promising. But as he noted, the issue of leap years still exists. I also found some additional dates unrelated to leapyears that resulted in an incorrect result when using that base date method. for example,
checking 4/30/2011 to 6/30/2011 resulted in 2 months, 2 days when it should be just 2 months. Note that my test for validity is that after determining the days/months/years difference between a startdate and enddate, i should be able to add the years/months/days
back to the startdate and arrive back at the original enddate.

The method from bmhc is fundamentally no different that Paul's.

The method from vaibhav_shah1988 fared a bit better in results, but it also return invalids results for some cases. for example, checking 1/1/2010 to 12/31/2012 resulted in 3 years when it should be just 2 years 11 months 30 days. There seems to be an edge
case bug in that code where going from the first day of a year to the last day of a year lands you on a Days value of -1.

Rather than getting too complex and looping through the dates to get a final result, we could go in a completely different direction and just treat this as a basic math subtraction problem.

Instead of our numbers having 100's 10's and 1's columns, we have year's month's and day's columns

endYear endMonth endDay
- startYear startMonth startDay
------------------------------------
= years months days

And when subtracting, we subtract the columns from right to left and we borrow numbers from the left as needed to keep each columns result from going negative. Borrowing from years to months is easy as years always have 12 months. Borrowing from months
to days is a little trickier as not all months have the same number of days and there's the issue of that pesky little leapyear month. But it turns out to be a relatively easy thing to do anyways.

So here's a twist on a time span class that does the math on the dates.

public class TimeSpan2
{
private int _years;
private int _months;
private int _days;
public int Years
{
get { return _years; }
}
public int Months
{
get { return _months; }
}
public int Days
{
get { return _days; }
}
public TimeSpan2(DateTime startDate, DateTime endDate)
{
//for simplicity, let's keep the TimeSpan2 to positive time spans
if (startDate > endDate)
{
DateTime tmpSwap = startDate;
startDate = endDate;
endDate = tmpSwap;
}
int startYear = startDate.Year;
int startMonth = startDate.Month;
int startDay = startDate.Day;
int endYear = endDate.Year;
int endMonth = endDate.Month;
int endDay = endDate.Day;
//perform the date math by subtracting startdate from enddate
//we actually subtract using the individual y/m/d pieces
//borrowing from the left as needed to avoid going negative...
// working on the 1's / day's column
if (endDay < startDay)
{
//borrow days from months column
//use previous month so we can see exactly how many days it actually has
DateTime previousMonth = endDate.AddMonths(-1);
endDay += DateTime.DaysInMonth(previousMonth.Year, previousMonth.Month);
//decrement our endmonth number since we just borrowed a month
endMonth -= 1;
//watch for invalid month and borrow from the years column if needed
if (endMonth < 1)
{
endMonth += 12;
endYear -= 1;
}
}
// working on the 10's / month's column
if (endMonth < startMonth)
{
//borrow months from the years column
endMonth += 12;
endYear -= 1;
}
_years = endYear - startYear;
_months = endMonth - startMonth;
_days = endDay - startDay;
}
public override string ToString()
{
//build up date parts and pluralize as needed
const string plural = "s";
//years and months not shown if they are zero but days are.
string yearString = (Years == 0 ? string.Empty : string.Format("{0} year{1}, ", Years, (Years > 1 ? plural : string.Empty))).ToString();
string monthString = (Months == 0 ? string.Empty : string.Format("{0} month{1} and ", Months, (Months > 1 ? plural : string.Empty))).ToString();
string dayString = string.Format("{0} day{1}", Days, (Days != 1 ? plural : string.Empty));
return string.Format("{0}{1}{2}", yearString, monthString, dayString);
}
}

using the class is as simple as:

DateTime startdate = new DateTime(2011, 1, 22);
DateTime enddate = new DateTime(2012, 5, 17);
Debug.WriteLine(new TimeSpan2(startdate, enddate));

I ran a number of tests to insure that the errors noted in the other techniques were not present and that it could cross over leap years without issue. Here are the test results contrasting the math based technique with the base date technique.

Notice that sometimes that Basedate algorithm gave a slightly different result that the TimeSpan2, but i colored it green (it was ok) if adding it back to the startdate landed you on the original enddate. The pink boxes indicate where adding the years,months,days
back to the startdate resulted in a different enddate.

Test Case

TimeSpan2 Algorithm

Basedate Algorithm

Check short month to long month: 2/1/2011 to 3/1/2011

1 month and 0 days

0 years, 0 months and 28 days

Check short month to long month: 2/15/2011 to 3/15/2011

1 month and 0 days

0 years, 0 months and 28 days

Check long month to short month: 1/1/2011 to 2/1/2011

1 month and 0 days

0 years, 1 months and 0 days

Check long month to short month: 1/31/2011 to 2/28/2011

28 days

0 years, 0 months and 28 days

Check long month to long month: 1/1/2011 to 3/1/2011

2 months and 0 days

0 years, 2 months and 0 days

Check long month to long month: 1/31/2011 to 3/31/2011

2 months and 0 days

0 years, 2 months and 0 days

Check short month to short month: 2/1/2011 to 4/1/2011

2 months and 0 days

0 years, 2 months and 0 days

Check short month to short month: 4/30/2011 to 6/30/2011

2 months and 0 days

0 years, 2 months and 2 days - Invalid

Check short month to short month: 2/28/2011 to 4/30/2011

2 months and 2 days

0 years, 2 months and 2 days

Check short month to long month: 4/30/2011 to 5/30/2011

1 month and 0 days

0 years, 0 months and 30 days

Check short month to long month: 4/30/2011 to 5/31/2011

I think it depends on how you frame the problem. I took the question at face value "How do you express x days in years/months/days". How many years/months/days between two given dates is a different problem. For example, 61 days could be called 0/2/2
if the months in question are Jan and Feb (non-leap) or 0/2/1 if Jan and Feb (leap). Those same 61 days could be from 30/4/11 to 30/6/11 in which case you would expect an answer of 0/2/0 (unless you included both start and end date in which case the answer
would be 0/2/1). It just depends on the problem you are trying to solve.

hi donpisci here is your short code and short answer

public void CalculateDays()
{
int months = 0;
int Days = 473;
int years = 0;
string time = null;
if (Days >= 365) {
years = Days / 365;
Days = Days % (365);
}
if (Days >= 30) {
months = Days / 30;
Days = Days % 30;
}
time = years.ToString() + " year " + months.ToString() + " months " + Days.ToString() + " days";
}

I did have a go writing a method myself, but couldn't get it to tally up with the calculator
here. As you can see, it has the answer (for the difference between 25/01/2011 and 18/04/2014 as 3 years, 2 months and 25 days. For all of the examples that I have tried, I've got something similar to 2 years, 11 months and 24 days (this includes mbanavige
code sample, which is the most accurate and what I'll be using in the meantime).

At the moment, we are not too fussed about leap years and such and are assuming that a month is 30 days long. I know that this means there will be a margin of error, but it shouldn't be by too much.

Thanks again for all of your help, and keep it coming! We can get through it together! :)

Here's my code which seems to be similar to some of what you've posted:

private string calculateTimeLeft(string inputTime)
{
int time = int.Parse(inputTime);
string totalYears = "";
string totalMonths = "";
string total;
int years = 0;
int months = 0;
//Find out how many years
if (time >= 365)
{
//Need to divide time by 365 to find the number of years
years = time / 365;
int yearsToRemove = years * 365;
time = time - yearsToRemove;
}
if (time >= 30)
{
//Need to divide time by 30 to get the number of months
months = time / 30;
int monthsToRemove = months * 30;
time = time - monthsToRemove;
}
totalYears = " and " + years + " year(s)";
totalMonths = ", " + months + " month(s) ";
total = time + " day(s)";
return total + totalMonths + totalYears;
}

I did have a go writing a method myself, but couldn't get it to tally up with the calculator
here. As you can see, it has the answer (for the difference between 25/01/2011 and 18/04/2014 as 3 years, 2 months and 25 days. For all of the examples that I have tried, I've got something similar to 2 years, 11 months and 24 days (this includes mbanavige
code sample, which is the most accurate and what I'll be using in the meantime).

The code sample i posted when run like this:

Debug.WriteLine(new TimeSpan2(new DateTime(2011, 1, 25), new DateTime(2014, 4, 18)));

should result in this answer (which is not inclusive of the start date):

3 years, 2 months and 24 days

The code that Paul posted using the basedate technique should also result in the same answer of:

3 years, 2 months and 24 days

The site you're linking to specifies that it's inclusive of the start and end date - hence it comes back with one additional day : 3 years, 2 months and 25 days.

When looking at time remaining till some future date, i think you would not want to include that extra day that the other website is including.

for example, if something were due tomorrow, then the time remaining (until tomorrow) would be just 1 day i think and not 2. but the technique on that other site will report 2 days as it counts the current day.

I suppose it could depend on how you will use it whether it's appropriate to count the current day.

## donpisci

Member

74 Points

178 Posts

## Convert number of days to days/ months/ years

Jan 21, 2011 02:00 PM|donpisci|LINK

Hi All,

I'm currently building a webservice and my client has asked me to return the time remaining until a particular date. I'm able to calculate the number of days remaining, but ideally instead of having 473 days for example, I would be able to show something like '1 year 4 months and 12 days'

Any ideas?

Thanks in advance!

## rtpHarry

All-Star

57144 Points

9040 Posts

## Re: Convert number of days to days/ months/ years

Jan 21, 2011 02:16 PM|rtpHarry|LINK

Hey,

You can use DateTime.AddDays() to add the number of days on to today (DateTime.Now).

Its not built into .net but Scott Mitchell covers how to make a relative date string such as your example in this article:

## budugu

All-Star

41312 Points

6053 Posts

## Re: Convert number of days to days/ months/ years

Jan 21, 2011 02:18 PM|budugu|LINK

If you subtract two dates, that will return an instance of TimeSpan, which will represent the difference between the two dates. Like this..

Getting in

yearsand days is more complex, because of leapyears."Don't be afraid to be wrong; otherwise you'll never be right."

## rajsedhain

Contributor

4235 Points

1081 Posts

## Re: Convert number of days to days/ months/ years

Jan 21, 2011 05:03 PM|rajsedhain|LINK

DateTime StartDate = Convert.ToDateTime("01/1/2010");

DateTime EndDate = Convert.ToDateTime("04/3/2011");

string strResult = CalculateDays(StartDate, EndDate);

public string CalculateDays(DateTime StartDate, DateTime EndDate)

{

DateTime oldDate;

DateTime.TryParse(StartDate.ToShortDateString(), out oldDate);

DateTime currentDate = EndDate;

TimeSpan difference = currentDate.Subtract(oldDate);

// This is to convert the timespan to datetime object

DateTime DateTimeDifferene = DateTime.MinValue + difference;

// Min value is 01/01/0001

// subtract our addition or 1 on all components to get the

//actual date.

int InYears = DateTimeDifferene.Year - 1;

int InMonths = DateTimeDifferene.Month - 1;

int InDays = DateTimeDifferene.Day - 1;

return InYears.ToString() +" Years "+ InMonths.ToString() +" Months " + InDays.ToString() +" Days";

}

Raj Sedhain

## SGWellens

All-Star

126093 Points

10328 Posts

Moderator

## Re: Convert number of days to days/ months/ years

Jan 21, 2011 05:17 PM|SGWellens|LINK

In your example, the above line does nothing (it converts a datetime to a string and then back to a datetime). If you were trying to strip the time component from a DateTime this is the way to do it:

oldDate = StartDate.Date;

My blog

## Paul Linton

Star

14649 Points

2763 Posts

## Re: Convert number of days to days/ months/ years

Jan 22, 2011 01:43 AM|Paul Linton|LINK

You could add the days to a known base date and then extract the components and subtract the base. Like this

You will get different results depending on which base year you use because of leap years (as noted above). For example, if you have 59 days and a base of 1/1/1 you get 2 months and 0 days, for a base date of 1/1/2000 you get 1 months and 28 days. Take your pick.

freepdf.## bmhc

Member

152 Points

60 Posts

## Re: Convert number of days to days/ months/ years

Jan 22, 2011 12:17 PM|bmhc|LINK

Here you go:

The -1 for the year, month and day in the string.Format is needed because, well, we start in the year 1 month 1 and day 1 so if numberOfDays = 1 we are in year 1, month 1 and day 2.

Good luck!

And mark the post answered if this works for you ;)

## vaibhav_shah...

Member

403 Points

114 Posts

## Re: Convert number of days to days/ months/ years

Jan 22, 2011 05:15 PM|vaibhav_shah1988|LINK

You can use this code also

DateTime StartDate = DateTime.Now;

DateTime EndDate = Convert.ToDateTime("12/31/2015");

string timeStr = "";

int yr = 0;

int mth = 0;

int days = 0;

TimeSpan ts = new TimeSpan();

ts = EndDate.Subtract(StartDate);

yr = (ts.Days / 365);

do

{

for (int i = 0; i <= 12; i++)

{

if (EndDate.Subtract(StartDate.AddYears(yr).AddMonths(i)).Days > 0)

{

mth = i;

}

else

{

break;

}

}

if (mth > 12)

yr = yr + 1;

} while (mth > 12);

days = EndDate.Subtract(StartDate.AddYears(yr).AddMonths(mth)).Days;

if (yr == 1)

timeStr += yr.ToString() + " year ";

else if (yr > 0)

timeStr += yr.ToString() + " years ";

if (mth == 1)

timeStr += mth.ToString() + " month ";

else if (mth > 0)

timeStr += mth.ToString() + " months ";

if (days == 1)

timeStr += days.ToString() + " day ";

else if (days > 0)

timeStr += days.ToString() + " days";

Label1.Text= timeStr;

Click Here For More Answers

## mbanavige

All-Star

137284 Points

16178 Posts

ASPInsiders

Moderator

## Re: Convert number of days to days/ months/ years

Jan 23, 2011 01:08 AM|mbanavige|LINK

Using the timespan has limitations as it doesnt do months and years. Even the Scott Mitchell acticle stops with Days as it used a timespan.

Paul's method was nice and concise and looked promising. But as he noted, the issue of leap years still exists. I also found some additional dates unrelated to leapyears that resulted in an incorrect result when using that base date method. for example, checking 4/30/2011 to 6/30/2011 resulted in 2 months, 2 days when it should be just 2 months. Note that my test for validity is that after determining the days/months/years difference between a startdate and enddate, i should be able to add the years/months/days back to the startdate and arrive back at the original enddate.

The method from bmhc is fundamentally no different that Paul's.

The method from vaibhav_shah1988 fared a bit better in results, but it also return invalids results for some cases. for example, checking 1/1/2010 to 12/31/2012 resulted in 3 years when it should be just 2 years 11 months 30 days. There seems to be an edge case bug in that code where going from the first day of a year to the last day of a year lands you on a Days value of -1.

Rather than getting too complex and looping through the dates to get a final result, we could go in a completely different direction and just treat this as a basic math subtraction problem.

Instead of our numbers having 100's 10's and 1's columns, we have year's month's and day's columns

endYear endMonth endDay

- startYear startMonth startDay

------------------------------------

= years months days

And when subtracting, we subtract the columns from right to left and we borrow numbers from the left as needed to keep each columns result from going negative. Borrowing from years to months is easy as years always have 12 months. Borrowing from months to days is a little trickier as not all months have the same number of days and there's the issue of that pesky little leapyear month. But it turns out to be a relatively easy thing to do anyways.

So here's a twist on a time span class that does the math on the dates.

using the class is as simple as:

I ran a number of tests to insure that the errors noted in the other techniques were not present and that it could cross over leap years without issue. Here are the test results contrasting the math based technique with the base date technique.

Notice that sometimes that Basedate algorithm gave a slightly different result that the TimeSpan2, but i colored it green (it was ok) if adding it back to the startdate landed you on the original enddate. The pink boxes indicate where adding the years,months,days back to the startdate resulted in a different enddate.

I always enjoy a good puzzle... [:)]

## Paul Linton

Star

14649 Points

2763 Posts

## Re: Convert number of days to days/ months/ years

Jan 23, 2011 04:54 AM|Paul Linton|LINK

I think it depends on how you frame the problem. I took the question at face value "How do you express x days in years/months/days". How many years/months/days between two given dates is a different problem. For example, 61 days could be called 0/2/2 if the months in question are Jan and Feb (non-leap) or 0/2/1 if Jan and Feb (leap). Those same 61 days could be from 30/4/11 to 30/6/11 in which case you would expect an answer of 0/2/0 (unless you included both start and end date in which case the answer would be 0/2/1). It just depends on the problem you are trying to solve.

freepdf.## mbanavige

All-Star

137284 Points

16178 Posts

ASPInsiders

Moderator

## Re: Convert number of days to days/ months/ years

Jan 23, 2011 12:44 PM|mbanavige|LINK

i think we also need to consider this portion of the question

## SGWellens

All-Star

126093 Points

10328 Posts

Moderator

## Re: Convert number of days to days/ months/ years

Jan 23, 2011 02:10 PM|SGWellens|LINK

I think the real puzzle is how you are able to spend so much time on this.

I suggest this solution:

My blog

## NewProgramer

Member

394 Points

246 Posts

## Re: Convert number of days to days/ months/ years

Jan 25, 2011 04:37 AM|NewProgramer|LINK

hi donpisci here is your short code and short answer

and the answer is

1 year 3 months 18 days

Please mark as answer if you find

## donpisci

Member

74 Points

178 Posts

## Re: Convert number of days to days/ months/ years

Jan 25, 2011 02:21 PM|donpisci|LINK

Hi Everyone,

Thanks for all of your responses!

I did have a go writing a method myself, but couldn't get it to tally up with the calculator here. As you can see, it has the answer (for the difference between 25/01/2011 and 18/04/2014 as 3 years, 2 months and 25 days. For all of the examples that I have tried, I've got something similar to 2 years, 11 months and 24 days (this includes mbanavige code sample, which is the most accurate and what I'll be using in the meantime).

At the moment, we are not too fussed about leap years and such and are assuming that a month is 30 days long. I know that this means there will be a margin of error, but it shouldn't be by too much.

Thanks again for all of your help, and keep it coming! We can get through it together! :)

Here's my code which seems to be similar to some of what you've posted:

## mbanavige

All-Star

137284 Points

16178 Posts

ASPInsiders

Moderator

## Re: Convert number of days to days/ months/ years

Jan 25, 2011 04:29 PM|mbanavige|LINK

The code sample i posted when run like this:

Debug.WriteLine(new TimeSpan2(new DateTime(2011, 1, 25), new DateTime(2014, 4, 18)));

should result in this answer (which is not inclusive of the start date):

3 years, 2 months and 24 days

The code that Paul posted using the basedate technique should also result in the same answer of:

3 years, 2 months and 24 days

The site you're linking to specifies that it's inclusive of the start and end date - hence it comes back with one additional day : 3 years, 2 months and 25 days.

When looking at time remaining till some future date, i think you would not want to include that extra day that the other website is including.

for example, if something were due tomorrow, then the time remaining (until tomorrow) would be just 1 day i think and not 2. but the technique on that other site will report 2 days as it counts the current day.

I suppose it could depend on how you will use it whether it's appropriate to count the current day.

## donpisci

Member

74 Points

178 Posts

## Re: Convert number of days to days/ months/ years

Jan 26, 2011 08:33 AM|donpisci|LINK

Mike,

I stand corrected.

There was a error with my handling of the date earlier on in the code.

Thanks for your help!