1

Is there some c# dates parser that returns from two dates a format like:

- two days
- one month
- two years

or something like that?

Example:

DateTime 1 = 10/11/2013

DateTime 2 = 11/12/2013

Output: "One month and one day"

I have searched and nothing was found about that kind of parser.

Gayot Fow
  • 8,710
  • 1
  • 35
  • 48
Phoenix_uy
  • 3,173
  • 9
  • 53
  • 100
  • Parsing? Or do you mean output in this format? – Colin Steel Oct 28 '13 at 16:54
  • I mean output from two DateTime objects selected by the user in two DateTimePickers – Phoenix_uy Oct 28 '13 at 16:56
  • 1
    Are you going from a `string` to a `DateTime` object -- parsing -- or are you going from a `DateTime` to a `string` -- output formatting? – JG in SD Oct 28 '13 at 16:59
  • Output formatting... from two DateTime objects to one single string – Phoenix_uy Oct 28 '13 at 17:01
  • It is a straight-forward exercise to take two dates and produce a string like "1y 2m 5d" as long as you stay within the Invariant Culture. Otherwise it's a bit more code-verbose, but still acheivable in the short-term. Is that what you're after? Something like "1y 3m"? – Gayot Fow Oct 28 '13 at 17:02
  • That's what i want... not the correct string output but that's what i mean – Phoenix_uy Oct 28 '13 at 17:05
  • 1
    Why don't you update your question with a sample input and output that explains the problem. Without a sample it isn't clear what you are attempting to do – Harrison Oct 28 '13 at 17:06
  • 1
    possible duplicate of [How do I calculate relative time?](http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time) – Harrison Oct 28 '13 at 17:10
  • Phoenix - it gets used a lot in investment banking applications, I'll have a look and answer if nobody else has... – Gayot Fow Oct 28 '13 at 17:10

3 Answers3

0

You should use an object of TimeSpan type, which you obtain by subtracting one DateTime from the other.

Then you simply need to work with formatting output string.

LittleSweetSeas
  • 6,786
  • 2
  • 21
  • 26
0

In measuring an interval, between two dates, and giving the result as a string in the form of "1Y 2M 3D", the natural assumption is to use the .NET TimeSpan class. But this assumption falls short because the TimeSpan measures only days, hours, minutes, and seconds and does not give any information about the number of, for example, elapsed months. Or years for that matter. That means you are left having to delve into the calendar to know how many days in a particular month and so on.

A helper method that can be used to solve the problem is...

  private static String Interval(DateTime start, DateTime end)
    {
        if (end <= start)
        {
            throw new Exception("Invalid interval");
        }
        int days = 0;
        int months = 0;
        int years = 0;
        DateTime temp = start;
        while (start.AddYears(years) <= end)
        {
            ++years;
        }
        --years;
        temp = temp.AddYears(years);
        while (temp.AddMonths(months) <= end)
        {
            ++months;
        }
        --months;
        temp = temp.AddMonths(months);
        while (temp.AddDays(days) <= end)
        {
            ++days;
        }
        --days;
        StringBuilder result = new StringBuilder();
        if (years > 0)
        {
            result.AppendFormat("{0}Y ", years);
        }
        if (months > 0)
        {
            result.AppendFormat("{0}M ", months);
        }
        if (days > 0)
        {
            result.AppendFormat("{0}D", days);
        }
        return result.ToString();
    }

This method increments various counters between two dates using native .NET methods and avoids having to use the calendar.

It produces these results

Start 22 Oct 2013  End 28 Oct 2013 => 6D
Start 23 Aug 2013  End 28 Oct 2013 => 2M 5D
Start  1 Jan 2012  End 28 Oct 2013 => 1Y 9M 27D

And so on...

You can use the same technique to resolve the interval down to minutes and seconds. And you can introduce weeks into the method by adding another variable and looping on it.

    while (temp.AddDays(weeks*7) <= end)
    {
        ++weeks;
    }
    --weeks;
    temp = temp.AddDays(weeks*7);

I'm sorry for the poor formatting, it seems the code formatter has gone south.

Triva: the legendary Jon Skeet took a crack at this same question, but then wrote that he didn't have time to complete the answer. How to get difference between two dates in Year/Month/Week/Day?

Community
  • 1
  • 1
Gayot Fow
  • 8,710
  • 1
  • 35
  • 48
-1
DateTime dateTime1 = new DateTime(2000, 01, 01, 0, 0, 0);
DateTime dateTime2 = new DateTime(2001, 02, 02, 10, 10, 10);
TimeSpan timeSpan1 = dateTime1 - dateTime2;
DateTime dateTime3 = new DateTime(timeSpan1.Ticks);
string string1 =
    dateTime3.Day + " days" +
    dateTime3.Month + " months" +
    dateTime3.Year + " years";

Is on the right track, you will still need to compute the values that you truly want, days of week, days by month, etc.

Colin Steel
  • 1,045
  • 1
  • 11
  • 24
  • 1
    That will not calculate the correct number of months as months have non uniform number of days in them, `new DateTime(timeSpan1.Ticks);` uses `1/1/0001 12:00:00 AM` as the start for it's calculations. If your start day is any other day than January 1st (or you go over a leap year day) the numbers may be off (test Feburary 1st to March 1st to check). EDIT: Your example throws a `ArgumentOutOfRangeException`, you need do `timeSpan1 = dateTime2 - dateTime1;` instead. – Scott Chamberlain Oct 28 '13 at 19:09