计算年,月,周和日

时间:2011-06-07 03:40:11

标签: c# .net date timespan

在我的应用程序中,用户输入两个日期。计划的开始日期和计划的结束日期。我们必须采用这些日期,并根据差异填充4个字段。

所以,让我们说他选择2010年1月1日作为开始,2011年3月2日作为结束,我们需要最终:

年:1 月份:2 周:0 第1天

意味着总持续时间为1年,2个月和1天。

有没有一种标准的方法可以做到这一点?或者我是否需要编写一个具有很多非常棘手的逻辑的方法来解决它?我希望我很幸运,并且会有一个date-diff类型.Net类可用。

11 个答案:

答案 0 :(得分:6)

这是一个完整的方法,不包括数周,但可以相对简单地添加。这是一个有点复杂的问题(在stackoverflow上以多种方式提出问题,并且在很多方面都回答得很差),但是可以回答的问题。 TimeSpan对象为我们提供了我们需要的部分内容,但只能使用几天。我已经针对这种方法编写了大量测试,如果你发现了漏洞,请发表评论。

这将做的是比较2个日期,获取年,月,日,小时和分钟。 (例如某些事件发生在1年,6个月,3天,4小时和7分钟前)

因为这个问题已被提出并试图多次回答,我不确定这是否会引起注意,但如果是这样,它应该提供价值。

    public static void TimeSpanToDateParts(DateTime d1, DateTime d2, out int years, out int months, out int days, out int hours, out int minutes)
    {
        if (d1 < d2)
        {
            var d3 = d2;
            d2 = d1;
            d1 = d3;
        }

        var span = d1 - d2;

        months = 12 * (d1.Year - d2.Year) + (d1.Month - d2.Month);

        //month may need to be decremented because the above calculates the ceiling of the months, not the floor.
        //to do so we increase d2 by the same number of months and compare.
        //(500ms fudge factor because datetimes are not precise enough to compare exactly)
        if (d1.CompareTo(d2.AddMonths(months).AddMilliseconds(-500)) <= 0)
        {
            --months;
        }

        years = months / 12;
        months -= years * 12;

        if (months == 0 && years == 0)
        {
            days = span.Days;
        }
        else
        {
            var md1 = new DateTime(d1.Year, d1.Month, d1.Day);
            // Fixed to use d2.Day instead of d1.Day
            var md2 = new DateTime(d2.Year, d2.Month, d2.Day);
            var mDays = (int) (md1 - md2).TotalDays;

            if (mDays > span.Days)
            {
                mDays = (int)(md1.AddMonths(-1) - md2).TotalDays;
            }

            days = span.Days - mDays;


        }
        hours = span.Hours;
        minutes = span.Minutes;
    }

答案 1 :(得分:4)

我认为TimeSpan正是您所寻找的,但它不需要数年或数月,因为它们的长度各不相同。

以下示例来自上述链接;

// Define two dates.
DateTime date1 = new DateTime(2010, 1, 1, 8, 0, 15);
DateTime date2 = new DateTime(2010, 8, 18, 13, 30, 30);
// Calculate the interval between the two dates.
TimeSpan interval = date2 - date1;
Console.WriteLine("{0} - {1} = {2}", date2, date1, interval.ToString());
// Display individual properties of the resulting TimeSpan object.
Console.WriteLine("   {0,-35} {1,20}", "Value of Days Component:", interval.Days);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Days:", interval.TotalDays);
Console.WriteLine("   {0,-35} {1,20}", "Value of Hours Component:", interval.Hours);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Hours:", interval.TotalHours);
Console.WriteLine("   {0,-35} {1,20}", "Value of Minutes Component:", interval.Minutes);
Console.WriteLine("   {0,-35} {1,20}", "Total Number of Minutes:", interval.TotalMinutes);
Console.WriteLine("   {0,-35} {1,20:N0}", "Value of Seconds Component:", interval.Seconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Total Number of Seconds:", interval.TotalSeconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Value of Milliseconds Component:", interval.Milliseconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Total Number of Milliseconds:", interval.TotalMilliseconds);
Console.WriteLine("   {0,-35} {1,20:N0}", "Ticks:", interval.Ticks);
// the example displays the following output:
//       8/18/2010 1:30:30 PM - 1/1/2010 8:00:15 AM = 229.05:30:15
//          Value of Days Component:                             229
//          Total Number of Days:                   229.229340277778
//          Value of Hours Component:                              5
//          Total Number of Hours:                  5501.50416666667
//          Value of Minutes Component:                           30
//          Total Number of Minutes:                       330090.25
//          Value of Seconds Component:                           15
//          Total Number of Seconds:                      19,805,415
//          Value of Milliseconds Component:                       0
//          Total Number of Milliseconds:             19,805,415,000
//          Ticks:                               198,054,150,000,000

答案 2 :(得分:4)

您可以使用this免费库的 DateDiff 类:

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29
} // DateDiffSample

答案 3 :(得分:1)

调查C#TimeSpan结构。它没有几个月或几年,但它确实需要几天。这使事情变得更容易。

答案 4 :(得分:1)

 public partial class Age1 : System.Web.UI.Page
    {
        private int Years;
        private int Months;
        private int Days;
        DateTime Cday;
        DateTime Bday;


        protected void Page_Load(object sender, EventArgs e)
        {
            txtCurrentDate.Enabled = false;
            txtCurrentDate.Text = DateTime.Now.ToString("g");
            Cday = Convert.ToDateTime(txtCurrentDate.Text);
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            Bday = Convert.ToDateTime(txtBirthdate.Text);
            AgeCaluclation(Bday, Cday);
            txtBirthdate.Text = "";
            txtCurrentDate.Text = "";
            lblAge.Text = this.Years+"  Years "+this.Months+"  Months " +this.Days+ "Days";
        }

        private Age1 AgeCaluclation(DateTime Bday, DateTime Cday)
        {

            if ((Cday.Year - Bday.Year) > 0 || 
               (((Cday.Year - Bday.Year) == 0) && 
               ((Bday.Month < Cday.Month) ||
               ((Bday.Month == Cday.Month) && 
               (Bday.Day <= Cday.Day)))))
            {

                int DaysInBdayMonth = DateTime.DaysInMonth(Bday.Year, Bday.Month);
                int DaysRemain = Cday.Day + (DaysInBdayMonth - Bday.Day);

                    if(Cday.Month > Bday.Month)
                    {
                        this.Years = Cday.Year - Bday.Year;
                        this.Months = Cday.Month - (Bday.Month + 1) + Math.Abs(DaysRemain / DaysInBdayMonth);
                        this.Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                    }
                    else if (Cday.Month == Bday.Month)
                    {
                        if (Cday.Day >= Bday.Day)
                        {
                            this.Years = Cday.Year - Bday.Year;
                            this.Months = 0;
                            this.Days = Cday.Day - Bday.Day;
                        }
                        else
                        {
                            this.Years = (Cday.Year - 1) - Bday.Year;
                            this.Months = 11;
                            this.Days = DateTime.DaysInMonth(Bday.Year, Bday.Month) - (Bday.Day - Cday.Day);

                        }
                    }
                    else
                    {
                        this.Years = (Cday.Year - 1) - Bday.Year;
                        this.Months = Cday.Month + (11 - Bday.Month) + Math.Abs(DaysRemain / DaysInBdayMonth);
                        this.Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                    }
            }
            else
            {
                throw new ArgumentException("Birthday date must be earlier than current date");
            }
            return this;
        }

    }

AgeCaluclationUsingC# and Asp.net Amazing

答案 5 :(得分:1)

我也需要这个,但就我而言,没有周数部分(所以只有几年,几个月和几天)。鉴于此,这就是我所做的:

DateTime startDate = DateTime.ParseExact (start, "dd/MM/yyyy",CultureInfo.InvariantCulture);
DateTime endDate = DateTime.ParseExact (end, "dd/MM/yyyy",CultureInfo.InvariantCulture);
int days=0;
int months = 0;
int years = 0;
//calculate days
if (endDate.Day >= startDate.Day) {
    days = endDate.Day - startDate.Day;
} else {
    var tempDate = endDate.AddMonths (-1);
    int daysInMonth = DateTime.DaysInMonth (tempDate.Year, tempDate.Month);
    days = daysInMonth - (startDate.Day - endDate.Day);
    months--;
}
//calculate months
if (endDate.Month >= startDate.Month) {
    months+=endDate.Month - startDate.Month;
} else {
    months+= 12 - (startDate.Month - endDate.Month);
    years--;
}
//calculate years
years+=endDate.Year - startDate.Year;
Debug.WriteLine (string.Format("{0} years, {1} months, {2} days",years,months,days));

如果您想更动态地展示它,您也可以使用以下代码:

//build the string
var result = "";
if (years!=0){
    result = years == 1 ? years + " year" : years + " years";
}
if (months != 0) {
    if (result != "") {
        result += ", ";
    }
    result += months == 1 ? months + " month" : months + " months";
}
if (days != 0) {
    if (result != "") {
        result += ", ";
    }
    result += days == 1 ? days + " day" : days + " days";
}
Debug.WriteLine (result);

答案 6 :(得分:1)

这应该可以。关键是如果给定的 2 个日期之间有奇数个闰日,则将天数减少 1。

    /// <summary>
    /// //Assume DateTime dt1 < DateTime dt2, print out difference between dt1 to dt2 in years, months, weeks and days
    /// </summary>
    /// <param name="dt1"></param>
    /// <param name="dt2"></param>
    static void DateDiff(DateTime dt1, DateTime dt2)
    {
        DateTime zeroTime = new DateTime(1, 1, 1);

        int leapDaysInBetween = CountLeapDays(dt1, dt2);

        TimeSpan span = dt2 - dt1;

        int years = (zeroTime + span).Year - 1;
        int months = (zeroTime + span).Month - 1;
        int days = (zeroTime + span).Day - (leapDaysInBetween % 2 == 1 ? 1 : 0);
        int weeks = days / 7;
        int remainingdays = days % 7;

        Console.WriteLine(String.Format("\nThe difference between date {0} and date {1} is: \n\t {2} year(s), {3} month(s), and {4} day(s).", dt1, dt2, years, months, days));
        Console.WriteLine(String.Format("\nThe difference between date {0} and date {1} is: \n\t {2} year(s), {3} month(s), {4} week(s) and {5} day(s).", dt1, dt2, years, months, weeks, remainingdays));
    }

    private static int CountLeapDays(DateTime dt1, DateTime dt2)
    {
        int leapDaysInBetween = 0;
        int year1 = dt1.Year, year2 = dt2.Year;
        DateTime dateValue;

        for (int i = year1; i <= year2; i++)
        {
            if (DateTime.TryParse("02/29/" + i.ToString(), out dateValue))
            {
                if (dateValue >= dt1 && dateValue <= dt2)
                    leapDaysInBetween++;
            }
        }

        return leapDaysInBetween;
    }

已运行这些测试:

static void Main(string[] args)
{
    DateDiff(new DateTime(2010, 1, 1), new DateTime(2012, 2, 9));
    DateDiff(new DateTime(2010, 1, 1), new DateTime(2012, 4, 9));
    DateDiff(new DateTime(2010, 1, 1), new DateTime(2020, 2, 9));
    DateDiff(new DateTime(2010, 1, 1), new DateTime(2020, 4, 9));
    DateDiff(new DateTime(2020, 2, 29), new DateTime(2021, 2, 28));
    DateDiff(new DateTime(2019, 2, 28), new DateTime(2021, 2, 28));
}

这些是打印输出:

日期 1/1/2010 12:00:00 AM 和日期 4/9/2012 12:00:00 AM 之间的差异是: 2年3个月9天。

日期 1/1/2010 12:00:00 AM 和日期 4/9/2012 12:00:00 AM 之间的差异是: 2年3个月1周2天。

日期 1/1/2010 12:00:00 AM 和日期 2/9/2020 12:00:00 AM 之间的差异是: 10 年 1 个月 9 天。

日期 1/1/2010 12:00:00 AM 和日期 2/9/2020 12:00:00 AM 之间的差异是: 10年1个月1周2天。

日期 1/1/2010 12:00:00 AM 和日期 4/9/2020 12:00:00 AM 之间的差异是: 10年3个月9天。

日期 1/1/2010 12:00:00 AM 和日期 4/9/2020 12:00:00 AM 之间的差异是: 10年3个月1周2天。

日期 2/29/2020 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 1 年、0 个月和 0 天。

日期 2/29/2020 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 1 年、0 个月、0 周和 0 天。

日期 2/28/2019 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 2年0个月1天。

日期 2/28/2019 12:00:00 AM 和日期 2/28/2021 12:00:00 AM 之间的差异是: 2年0个月0周1天。

答案 7 :(得分:0)

我创建了这个用于返回两个日期之间的年,月和日的差异。

public static Dictionary<string, int> TimeSpanToDateParts(DateTime fromDate,DateTime toDate)
        {
            int years;
            int months;
            int days;
            Dictionary<string, int> dateParts = new Dictionary<string, int>();
            if (toDate < fromDate)
            {
               return TimeSpanToDateParts(toDate,fromDate);
            }

            var span = toDate - fromDate;

            months = 12 * (toDate.Year - fromDate.Year) + (toDate.Month - fromDate.Month);

            if (toDate.CompareTo(fromDate.AddMonths(months).AddMilliseconds(-500)) <= 0)
            {
                --months;
            }

            years = months / 12;
            months -= years * 12;

            if (months == 0 && years == 0)
            {
                days = span.Days;
            }
            else
            {
                days = toDate.Day;
                if (fromDate.Day > toDate.Day)
                    days = days + (DateTime.DaysInMonth(toDate.Year, toDate.Month - 1) - fromDate.Day);
                else
                    days = days - fromDate.Day;
            }
            dateParts.Add("Years", years);
            dateParts.Add("Months", months);
            dateParts.Add("Days", days);

            return dateParts;
        }

答案 8 :(得分:0)

如果您首先计算总月份数和总天数,逻辑不会过于复杂。然后很容易用除法和模做一些整数数学。

DateTime start_date = new DateTime(2010, 1, 1);
DateTime end_date = new DateTime(2011, 3, 2);

int diff_years = end_date.Year - start_date.Year;
int diff_months = end_date.Month - start_date.Month;

int total_months = 12 * diff_years + diff_months;
DateTime near_end_date = start_date.AddMonths(total_months);
int total_days = (int)end_date.Subtract(near_end_date).TotalDays;

int years = total_months / 12;
int months = total_months % 12;
int weeks = total_days / 7;
int days = total_days % 7;

Console.WriteLine($"Years: {years} Months: {months} Weeks: {weeks} Days: {days}");

这如预期的那样给出了 Years: 1 Months: 2 Weeks: 0 Days: 1

答案 9 :(得分:0)

这是我刚刚构建的转换器。我没有尝试过上述所有解决方案,但我尝试过的所有解决方案仍然以某种方式略微偏离。这考虑了年、闰年、月、周、天等,然后获取最后 YM 或 MW 或 WD 或 DH 的两个最有用的值。这很简单,但我的项目需要它,也许对未来的人有帮助。当然,如果这出于某种原因或其他原因不好,我相信你们都会告诉我。

        DateTime beforeDate = topic.lastActive.ToLocalTime();
        DateTime futureDate = DateTime.Now.ToLocalTime();

        int minutes = 0;
        int hours = 0;
        int days = 0;
        int weeks = 0;
        int months = 0;
        int years = 0;

        Dictionary<int, int> dictMonths = new Dictionary<int, int> { };
        dictMonths.Add(1, 31);
        if (DateTime.IsLeapYear(futureDate.Year))
            dictMonths.Add(2, 29);
        else
            dictMonths.Add(2, 28);
        dictMonths.Add(3, 31);
        dictMonths.Add(4, 30);
        dictMonths.Add(5, 31);
        dictMonths.Add(6, 30);
        dictMonths.Add(7, 31);
        dictMonths.Add(8, 31);
        dictMonths.Add(9, 30);
        dictMonths.Add(10, 31);
        dictMonths.Add(11, 30);
        dictMonths.Add(12, 31);

        //Time difference between dates
        TimeSpan span = futureDate - beforeDate;
        hours = span.Hours;
        minutes = span.Minutes;

        //Days total
        days = span.Days;
        //Find how many years
        DateTime zeroTime = new DateTime(1, 1, 1);

        // Because we start at year 1 for the Gregorian
        // calendar, we must subtract a year here.
        years = (zeroTime + span).Year - 1;
        //find difference of days of years already found
        int startYear = futureDate.Year - years;
        for (int i = 0; i < years; i++)
        {
            if (DateTime.IsLeapYear(startYear))
                days -= 366;
            else
                days -= 365;

            startYear++;
        }
        //Find months by multiplying months in year by difference of datetime years then add difference of current year months
        months = 12 * (futureDate.Year - beforeDate.Year) + (futureDate.Month - beforeDate.Month);
        //month may need to be decremented because the above calculates the ceiling of the months, not the floor.
        //to do so we increase before by the same number of months and compare.
        //(500ms fudge factor because datetimes are not precise enough to compare exactly)
        if (futureDate.CompareTo(beforeDate.AddMonths(months).AddMilliseconds(-500)) <= 0)
        {
            --months;
        }
        //subtract months from how many years we have already accumulated
        months -= (12 * years);
        //find how many days by compared to our month dictionary
        int startMonth = beforeDate.Month;
        for (int i = 0; i < months; i++)
        {
            //check if faulty leap year
            if (startMonth == 2 && (months - 1 > 10))
                days -= 28;
            else
                days -= dictMonths[startMonth];
            startMonth++;
            if (startMonth > 12)
            {
                startMonth = 1;
            }
        }
        //Find if any weeks are within our now total days
        weeks = days / 7;
        if (weeks > 0)
        {
            //remainder is days left
            days = days % 7;
        }

        Console.WriteLine(years + " " + months + " " + weeks + " " + days + " " + span.Hours + " " + span.Minutes);

        if (years > 0)
        {
            if (years > 1 && months > 1)
                return $"Latest Reply: {years} years, {months} months ago.";
            else if (years > 1 && months == 0)
                return $"Latest Reply: {years} years ago.";
            else if (years == 1 && months == 0)
                return $"Latest Reply: {years} year ago.";
            else if (years > 1)
                return $"Latest Reply: {years} years, {months} month ago.";
            else if (months > 1)
                return $"Latest Reply: {years} year, {months} months ago.";
            else
                return $"Latest Reply: {years} year, {months} month ago.";
        }
        else if (months > 0)
        {
            if (months > 1 && weeks > 1)
                return $"Latest Reply: {months} months, {weeks} weeks ago.";
            else if (months > 1 && weeks == 0)
                return $"Latest Reply: {months} months ago.";
            else if (months == 1 && weeks == 0)
                return $"Latest Reply: {months} month ago.";
            else if (months > 1)
                return $"Latest Reply: {months} months, {weeks} week ago.";
            else if (weeks > 1)
                return $"Latest Reply: {months} month, {weeks} weeks ago.";
            else
                return $"Latest Reply: {months} month, {weeks} week ago.";
        }
        else if (weeks > 0)
        {
            if (weeks > 1 && days > 1)
                return $"Latest Reply: {weeks} weeks, {days} days ago.";
            else if (weeks > 1 && days == 0)
                return $"Latest Reply: {weeks} weeks ago.";
            else if (weeks == 1 && days == 0)
                return $"Latest Reply: {weeks} week ago.";
            else if (weeks > 1)
                return $"Latest Reply: {weeks} weeks, {days} day ago.";
            else if (days > 1)
                return $"Latest Reply: {weeks} week, {days} days ago.";
            else
                return $"Latest Reply: {weeks} week, {days} day ago.";
        }
        else if (days > 0)
        {
            if (days > 1 && hours > 1)
                return $"Latest Reply: {days} days, {hours} hours ago.";
            else if (days > 1 && hours == 0)
                return $"Latest Reply: {days} days ago.";
            else if (days == 1 && hours == 0)
                return $"Latest Reply: {days} day ago.";
            else if (days > 1)
                return $"Latest Reply: {days} days, {hours} hour ago.";
            else if (hours > 1)
                return $"Latest Reply: {days} day, {hours} hours ago.";
            else
                return $"Latest Reply: {days} day, {hours} hour ago.";
        }
        else if (hours > 0)
        {
            if (hours > 1 && minutes > 1)
                return $"Latest Reply: {hours} hours, {minutes} minutes ago.";
            else if (hours > 1 && minutes == 0)
                return $"Latest Reply: {hours} hours ago.";
            else if (hours == 1 && minutes == 0)
                return $"Latest Reply: {hours} hour ago.";
            else if (hours > 1)
                return $"Latest Reply: {hours} hours, {minutes} minute ago.";
            else if (minutes > 1)
                return $"Latest Reply: {hours} hour, {minutes} minutes ago.";
            else
                return $"Latest Reply: {hours} hour, {minutes} minute ago.";
        }
        else if (minutes > 0)
        {
            if (minutes > 1)
                return $"Latest Reply: {minutes} minutes ago.";
            else
                return $"Latest Reply: {minutes} minute ago.";
        }
        else
        {
            return $"Latest Reply: Just now.";
        }

答案 10 :(得分:0)

这是一个很老的问题,但仍有时间试一试。

重要的是要考虑到月份有不同的天数。

    public static (int, int, int) GetYearsMonthsDaysDifference(DateTime date1, DateTime date2)
    {
        DateTime startDate = date1;
        DateTime endDate = date2;

        if (date1 > date2)
        {
            startDate = date2;
            endDate = date1;
        }

        var months = (endDate.Month + (12 - startDate.Month)) - (endDate.Day < startDate.Day ? 1 : 0);
        var years = (endDate.Year - startDate.Year - (months < 12 ? 1 : 0));
        months -= (months >= 12 ? 12 : 0);
        var days = endDate.DayOfYear - startDate.AddYears(years).AddMonths(months).DayOfYear;

        return (years, months, days);
    }