Рассчитать годы, месяцы, недели и дни

В моем приложении пользователь вводит две даты. Запланированная дата начала и запланированная дата окончания. Мы должны взять эти даты и заполнить 4 поля в зависимости от разницы.

Итак, допустим, он выбирает 1 января 2010 года в качестве начала и 2 марта 2011 года в качестве конца, нам нужно получить:

Годы: 1 Месяцы: 2 Недели: 0 Дней 1

Это означает, что общая продолжительность составляет 1 год, 2 месяца и 1 день.

Есть стандартный способ сделать это? Или мне нужно написать метод с довольно сложной логикой для его решения? Я надеялся, что мне повезет, и будет доступен класс .Net типа date-diff.


person Craig    schedule 07.06.2011    source источник
comment
Вы не получаете нужных ответов, поэтому вот версия T-SQL: stackoverflow.com/questions/57599/   -  person Gabe    schedule 07.06.2011
comment
Эта ссылка содержит ответ: stackoverflow.com/questions/1083955/   -  person Steve Wellens    schedule 07.06.2011
comment
См. Также: stackoverflow.com/questions/3054715/c -calculate-точный-возраст /   -  person Gabe    schedule 07.06.2011
comment
возможный дубликат Как узнать разницу между две даты в Год / Месяц / Неделя / День?   -  person marc_s    schedule 07.06.2011
comment
Я размещен в этой теме, код stackoverflow.com/questions/6260372/   -  person Shaik Raffi    schedule 06.11.2013


Ответы (11)


Вот полный метод, недели не включены, но можно относительно просто добавить. Это довольно сложный вопрос (задаваемый множеством способов в 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;
    }
person Chuck Rostance    schedule 18.07.2012
comment
этот не рассчитывает «Дни» правильно. Для 139 дней он должен дать 4 месяца и 19 дней, вместо этого он говорит 30 дней, что неверно. Также не хватает недель. - person Jhollman; 17.06.2019
comment
@Jhollman в некоторых месяцах 31 день. Промежуток между 01.03.2018 и 31.03.2019 составляет один год, ноль месяцев и 30 дней. Было бы неправильно называть это одним годом одним месяцем. - person Ross Presser; 19.05.2020

Вы можете использовать класс 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
person Community    schedule 07.06.2011

Мне тоже это было нужно, но в моем случае без недельной части (то есть только годы, месяцы и дни). Учитывая это, вот что я сделал:

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);
person Cristiano Santos    schedule 21.01.2016

Я думаю, что 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
person Christoph    schedule 07.06.2011
comment
Это только кажется, что обрабатывает значения времени ... максимум - часы. - person Craig; 07.06.2011
comment
Почему это получает голоса за? Это решение не отвечает на вопрос. Я не вижу лет, месяцев, недель и дней. - person Alex Aza; 07.06.2011
comment
Мне нравится ответ I think TimeSpan is what you are looking for, but it doesn't do what you asked for :) - person Alex Aza; 07.06.2011
comment
Как указал Стив У. stackoverflow.com/questions/1083955/ имеет принятый ответ. Однако этот ответ также не дает полного ответа на вопрос, но показывает сложности, связанные с такого рода расчетами. И он действительно отвечает на вопрос: есть ли стандартный способ сделать это? Или мне нужно написать метод с довольно сложной логикой для его решения? - person Christoph; 07.06.2011

 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 # и Asp.net Amazing

person Shaik Raffi    schedule 05.11.2013

Я создал это для возврата разницы в годах, месяцах и днях между двумя датами.

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;
        }
person Namith Krishnan    schedule 30.01.2018
comment
Спасибо за Ваш ответ. Было бы здорово, если бы вы также добавили в свой код краткое объяснение и несколько комментариев. Это поможет людям лучше понять ваш ответ. - person Andre Hofmeister; 30.01.2018
comment
Часть DaysInMonth () завершится ошибкой, если значение toDate находится в январе, потому что она вычитает 1 из значения месяца. Чтобы исправить: DateTime prevMonthDate = toDate.AddMonths (-1); days = days + (DateTime.DaysInMonth (prevMonthDate.Year, prevMonthDate.Month) - fromDate.Day); - person seagulledge; 04.01.2021

Это должно сработать. Ключ состоит в том, чтобы уменьшить количество дней на 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));
}

Вот распечатки:

Разница между датой 01.01.2010 12:00:00 AM и датой 04.09.2012 12:00:00 AM составляет: 2 года, 3 месяца и 9 дней.

Разница между датой 01.01.2010 12:00:00 AM и датой 04.09.2012 12:00:00 AM составляет: 2 года, 3 месяца, 1 неделя (недели) и 2 дня. (s).

Разница между датой 01.01.2010 12:00:00 AM и датой 09.02.2020 12:00:00 AM составляет: 10 лет, 1 месяц и 9 дней.

Разница между датой 01.01.2010 12:00:00 AM и датой 09.02.2020 12:00:00 AM составляет: 10 лет, 1 месяц, 1 неделя и 2 дня. (s).

Разница между датой 01.01.2010 12:00:00 AM и датой 09.04.2020 12:00:00 AM составляет: 10 лет, 3 месяца и 9 дней.

Разница между датой 01.01.2010 12:00:00 AM и датой 4/9/2020 12:00:00 AM составляет: 10 лет, 3 месяца, 1 неделю и 2 дня. (s).

Разница между датой 29.02.2020 12:00:00 и датой 28.02.2021 12:00:00 AM составляет: 1 год, 0 месяцев и 0 дней.

Разница между датой 29.02.2020 12:00:00 и датой 28.02.2021 12:00:00 AM составляет: 1 год (лет), 0 месяцев (месяцев), 0 недель (недель) и 0 дней. (s).

Разница между датой 28.02.2019 12:00:00 AM и датой 28.02.2021 12:00:00 AM составляет: 2 года, 0 месяцев и 1 день.

Разница между датой 28.02.2019 12:00:00 AM и датой 28.02.2021 12:00:00 AM составляет: 2 года, 0 месяцев, 0 недель и 1 день. (s).

person Steve Liu    schedule 05.05.2021
comment
Это, вероятно, лучшее приближение, которое я видел до сих пор, но оно также не совсем согласовано. Пример 1: с 31 января по 19 марта - 30 дней. В этом нет ничего плохого, но и не то, что вы ожидали. Когда у вас дата начала в январе и дата окончания в марте, разница должна составлять как минимум один месяц, не так ли? Пример 2: с 01.12.19 по 31.01.20 - 2 месяца 3 дня. Нет хорошего способа это объяснить. - person Mike Fuchs; 01.07.2021

Изучите структуру C # TimeSpan. Это не месяцы или годы, а дни. Это упрощает жизнь.

person Nik    schedule 07.06.2011

Логика не будет слишком сложной, если сначала вычислить общее количество месяцев и дней. Тогда легко выполнить небольшую математику с целыми числами с помощью div и mod.

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, как и ожидалось.

person Enigmativity    schedule 02.05.2021

Вот конвертер, который я только что построил. Я не пробовал все вышеперечисленные решения, но все те, которые я попробовал, так или иначе были немного неправильными. При этом учитываются годы, високосные годы, месяцы, недели, дни и т. Д., А затем извлекаются два наиболее полезных значения: последние 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.";
        }
person Carr O'Connor    schedule 14.05.2021

Это довольно старый вопрос, но все же пора попробовать.

Важно учитывать, что в месяцах разное количество дней.

    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);
    }
person dviana    schedule 13.07.2021