15 replies

Last post Jan 26, 2011 08:33 AM by donpisci

Member

19 Points

178 Posts

Convert number of days to days/ months/ years

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?

All-Star

39524 Points

8948 Posts

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

Hey,

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

```int NumberOfDays = 473;

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

All-Star

29295 Points

5968 Posts

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

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

```DateTime oldDate = new DateTime(2007, 8, 15);
DateTime newDate = DateTime.Now;
TimeSpan ts = newDate - oldDate;

Console.WriteLine("years: {0} ", ts.Days);
Console.WriteLine("hours: {0} ", ts.Hours);
Console.WriteLine("Minutes: {0} ", ts.Minutes);```

Getting in years and days is more complex, because of leapyears.

Vijay Kodali || My Blog

"Don't be afraid to be wrong; otherwise you'll never be right."

Contributor

2602 Points

1018 Posts

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

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";
}

Thanks,
Raj Sedhain
• SGWellens

All-Star

124312 Points

10174 Posts

Moderator

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

rajsedhain

DateTime oldDate;

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:

oldDate = StartDate.Date;

Steve Wellens

My blog

Star

9425 Points

2743 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

```var baseDate = new DateTime(1,1,1);
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.

Got a c# problem? Try .NET Book Zero from Charles Petzold, it's a free pdf.

Member

63 Points

60 Posts

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

Here you go:

```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 ;)

Member

221 Points

112 Posts

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

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++)
{
{
mth = i;
}
else
{
break;
}
}

if (mth > 12)
yr = yr + 1;
} while (mth > 12);

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;

"Mark As Answer" if it helps .

• mbanavige

All-Star

149171 Points

13015 Posts

ASPInsiders

Moderator

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

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
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 1 month and 1 day 0 years, 1 months and 0 days - Invalid Check leapyear: 2/28/2012 to 3/1/2012 2 days 0 years, 0 months and 2 days Check leapyear: 2/28/2012 to 3/31/2012 1 month and 3 days 0 years, 1 months and 1 days - Invalid Check leapyear: 2/1/2012 to 3/1/2012 1 month and 0 days 0 years, 0 months and 29 days Check crossing year end: 12/31/2011 to 1/1/2012 1 day 0 years, 0 months and 1 days Check forum post example: 1/22/2011 to 5/9/2012 1 year, 3 months and 17 days 1 years, 3 months and 18 days - Invalid

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

Mike Banavige

Star

9425 Points

2743 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.

Got a c# problem? Try .NET Book Zero from Charles Petzold, it's a free pdf.
• mbanavige

All-Star

149171 Points

13015 Posts

ASPInsiders

Moderator

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

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

donpisci

my client has asked me to return the time remaining until a particular date

Mike Banavige
• SGWellens

All-Star

124312 Points

10174 Posts

Moderator

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

mbanavige

I always enjoy a good puzzle...

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

I suggest this solution:

```int Days, Months, Years;      // Some algorithm
String Answer = String.Format("Approximately {0} Days, {1} Months, {2} Years", Days, Months, Years);
```
Steve Wellens

My blog

Member

113 Points

236 Posts

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

```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";
}```

1 year 3 months 18 days

Member

19 Points

178 Posts

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

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:

```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)";
}```
• mbanavige

All-Star

149171 Points

13015 Posts

ASPInsiders

Moderator

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

donpisci

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.

Mike Banavige

Member

19 Points

178 Posts