Разница в месяцах между двумя датами

Как рассчитать разницу в месяцах между двумя датами в C #?

Является ли эквивалентный метод VB DateDiff() в C #. Мне нужно найти разницу в месяцах между двумя датами, которые разделены годами. Документация говорит, что я могу использовать TimeSpan как:

TimeSpan ts = date1 - date2;

но это дает мне данные в днях. Я не хочу делить это число на 30 , потому что не каждый месяц равен 30 дням, и так как два значения операндов довольно сильно отличаются друг от друга, я боюсь, что деление на 30 может дать мне неправильное значение.

Есть предложения?

вопрос задан 9.01.2011
Rauf
4902 репутация

32 ответов


  • 361 рейтинг

    Предполагая, что день месяца не имеет значения (т.е. е. разница между 2011. 1. 1 и 2010. 12. 31 - 1) с датой 1 & gt; date2 дает положительное значение, а date2 & gt; date1 отрицательное значение

    ((date1.Year - date2.Year) * 12) + date1.Month - date2.Month
    

    Или, если вы хотите указать приблизительное количество «средних месяцев» между двумя датами, следующее должно работать для всех, кроме очень больших разниц в датах.

    date1.Subtract(date2).Days / (365.25 / 12)
    

    Обратите внимание: если вы должны использовать последнее решение, тогда в ваших модульных тестах должен быть указан самый широкий диапазон дат, с которым ваше приложение рассчитано для работы, и соответствующим образом проверить результаты расчета.


    Обновление (с благодарностью Гэри )

    При использовании метода «средних месяцев» чуть более точное число для «среднего числа дней в году» составляет 365. 2425 .

    ответ дан Adam Ralph, с репутацией 23483, 9.01.2011
  • 191 рейтинг

    Здесь представлено комплексное решение для возврата DateTimeSpan, аналогично TimeSpan, за исключением того, что оно включает все компоненты даты в дополнение к компонентам времени.

    Использование:

    void Main()
    {
        DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
        DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
        var dateSpan = DateTimeSpan.CompareDates(compareTo, now);
        Console.WriteLine("Years: " + dateSpan.Years);
        Console.WriteLine("Months: " + dateSpan.Months);
        Console.WriteLine("Days: " + dateSpan.Days);
        Console.WriteLine("Hours: " + dateSpan.Hours);
        Console.WriteLine("Minutes: " + dateSpan.Minutes);
        Console.WriteLine("Seconds: " + dateSpan.Seconds);
        Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
    }
    

    Выходы:

    Годы: 1
    Месяцев: 5
    Дней: 27
    Часы работы: 1
    Минут: 36
    Секунд: 50
    Миллисекунды: 0

    Для удобства я включил логику в структуру DateTimeSpan, но вы можете перемещать метод CompareDates, где считаете нужным. Также обратите внимание, что не имеет значения, какая дата предшествует другой.

    public struct DateTimeSpan
    {
        private readonly int years;
        private readonly int months;
        private readonly int days;
        private readonly int hours;
        private readonly int minutes;
        private readonly int seconds;
        private readonly int milliseconds;
    
        public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
        {
            this.years = years;
            this.months = months;
            this.days = days;
            this.hours = hours;
            this.minutes = minutes;
            this.seconds = seconds;
            this.milliseconds = milliseconds;
        }
    
        public int Years { get { return years; } }
        public int Months { get { return months; } }
        public int Days { get { return days; } }
        public int Hours { get { return hours; } }
        public int Minutes { get { return minutes; } }
        public int Seconds { get { return seconds; } }
        public int Milliseconds { get { return milliseconds; } }
    
        enum Phase { Years, Months, Days, Done }
    
        public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
        {
            if (date2 < date1)
            {
                var sub = date1;
                date1 = date2;
                date2 = sub;
            }
    
            DateTime current = date1;
            int years = 0;
            int months = 0;
            int days = 0;
    
            Phase phase = Phase.Years;
            DateTimeSpan span = new DateTimeSpan();
            int officialDay = current.Day;
    
            while (phase != Phase.Done)
            {
                switch (phase)
                {
                    case Phase.Years:
                        if (current.AddYears(years + 1) > date2)
                        {
                            phase = Phase.Months;
                            current = current.AddYears(years);
                        }
                        else
                        {
                            years++;
                        }
                        break;
                    case Phase.Months:
                        if (current.AddMonths(months + 1) > date2)
                        {
                            phase = Phase.Days;
                            current = current.AddMonths(months);
                            if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
                                current = current.AddDays(officialDay - current.Day);
                        }
                        else
                        {
                            months++;
                        }
                        break;
                    case Phase.Days:
                        if (current.AddDays(days + 1) > date2)
                        {
                            current = current.AddDays(days);
                            var timespan = date2 - current;
                            span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
                            phase = Phase.Done;
                        }
                        else
                        {
                            days++;
                        }
                        break;
                }
            }
    
            return span;
        }
    }
    
    ответ дан Kirk Woll, с репутацией 59574, 9.02.2012
  • 31 рейтинг

    Если вам нужно точное число полных месяцев, всегда положительное (2000-01-15, 2000-02-14 возвращает 0), учитывая, что полный месяц - это когда вы достигаете того же дня в следующем месяце (что-то вроде расчета возраста)

    public static int GetMonthsBetween(DateTime from, DateTime to)
    {
        if (from > to) return GetMonthsBetween(to, from);
    
        var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
    
        if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
        {
            return monthDiff - 1;
        }
        else
        {
            return monthDiff;
        }
    }
    

    Изменить причину: старый код был неверным в некоторых случаях, например:

    new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
    
    Test cases I used to test the function:
    
    var tests = new[]
    {
        new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
        new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
        new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
        new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
        new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
        new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
        new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
        new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
        new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
        new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
        new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
    };
    
    ответ дан Guillaume86, с репутацией 12797, 26.03.2012
  • 27 рейтинг

    Вы могли бы сделать

    if ( date1.AddMonths(x) > date2 )
    
    ответ дан Mongus Pong, с репутацией 8472, 20.09.2011
  • 22 рейтинг

    Я проверил использование этого метода в VB. NET через MSDN, и кажется, что он имеет много использования. В C # такого встроенного метода нет. (Даже если это не очень хорошая идея) вы можете вызывать VB в C #.

    1. Добавить Microsoft.VisualBasic.dll к ваш проект в качестве ссылки
    2. использовать Microsoft.VisualBasic.DateAndTime.DateDiff в вашем коде
    ответ дан Danny Chen, с репутацией 29256, 9.01.2011
  • 9 рейтинг

    Чтобы получить разницу в месяцах (включая начало и конец включительно), независимо от дат:

    DateTime start = new DateTime(2013, 1, 1);
    DateTime end = new DateTime(2014, 2, 1);
    var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
    
    ответ дан Chirag, с репутацией 2696, 5.04.2014
  • 6 рейтинг

    Мне просто нужно что-то простое, чтобы обслужить е. г. Даты трудоустройства, в которые вводится только месяц / год, так что нужны были разные годы и месяцы. Это то, что я использую, здесь только для полезности

    public static YearsMonths YearMonthDiff(DateTime startDate, DateTime endDate) {
        int monthDiff = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month) + 1;
        int years = (int)Math.Floor((decimal) (monthDiff / 12));
        int months = monthDiff % 12;
        return new YearsMonths {
            TotalMonths = monthDiff,
                Years = years,
                Months = months
        };
    }
    

    . NET Fiddle

    ответ дан jenson-button-event, с репутацией 10481, 6.12.2014
  • 4 рейтинг

    Вы можете использовать класс DateDiff библиотеки периода для. NET :

    // ----------------------------------------------------------------------
    public void DateDiffSample()
    {
      DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
      DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
      DateDiff dateDiff = new DateDiff( date1, date2 );
    
      // differences
      Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
      // > DateDiff.Months: 16
    
      // elapsed
      Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
      // > DateDiff.ElapsedMonths: 4
    
      // description
      Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) );
      // > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs
    } // DateDiffSample
    
    ответ дан does_not_exist, с репутацией , 5.04.2014
  • 3 рейтинг

    Использовать Noda Time :

    LocalDate start = new LocalDate(2013, 1, 5);
    LocalDate end = new LocalDate(2014, 6, 1);
    Period period = Period.Between(start, end, PeriodUnits.Months);
    Console.WriteLine(period.Months); // 16
    

    (пример источника)

    ответ дан Edward Brey, с репутацией 25409, 14.09.2015
  • 2 рейтинг

    Вот простое решение, которое работает по крайней мере для меня. Это, вероятно, не самый быстрый, потому что он использует классную функцию AddTonth DateTime в цикле:

    public static int GetMonthsDiff(DateTime start, DateTime end)
    {
        if (start > end)
            return GetMonthsDiff(end, start);
    
        int months = 0;
        do
        {
            start = start.AddMonths(1);
            if (start > end)
                return months;
    
            months++;
        }
        while (true);
    }
    
    ответ дан Simon Mourier, с репутацией 94839, 19.08.2016
  • 2 рейтинг

    Наиболее точный способ - вернуть разницу в месяцах по доле:

    private double ReturnDiffereceBetweenTwoDatesInMonths(DateTime startDateTime, DateTime endDateTime)
    {
        double result = 0;
        double days = 0;
        DateTime currentDateTime = startDateTime;
        while (endDateTime > currentDateTime.AddMonths(1))
        {
            result ++;
    
            currentDateTime = currentDateTime.AddMonths(1);
        }
    
        if (endDateTime > currentDateTime)
        {
            days = endDateTime.Subtract(currentDateTime).TotalDays;
    
        }
        return result + days/endDateTime.GetMonthDays;
    }
    
    ответ дан Saeed Mahmoudi, с репутацией 21, 7.11.2015
  • 2 рейтинг

    Это сработало для того, что мне было нужно. День месяца не имел значения в моем случае, потому что это всегда последний день месяца.

    public static int MonthDiff(DateTime d1, DateTime d2){
        int retVal = 0;
    
        if (d1.Month
    ответ дан Elmer, с репутацией 89, 9.05.2013
  • 1 рейтинг
    Public Class ClassDateOperation
        Private prop_DifferenceInDay As Integer
        Private prop_DifferenceInMonth As Integer
        Private prop_DifferenceInYear As Integer
    
    
        Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation
            Dim differenceInDay As Integer
            Dim differenceInMonth As Integer
            Dim differenceInYear As Integer
            Dim myDate As Date
    
            DateEnd = DateEnd.AddDays(1)
    
            differenceInYear = DateEnd.Year - DateStart.Year
    
            If DateStart.Month <= DateEnd.Month Then
                differenceInMonth = DateEnd.Month - DateStart.Month
            Else
                differenceInYear -= 1
                differenceInMonth = (12 - DateStart.Month) + DateEnd.Month
            End If
    
    
            If DateStart.Day <= DateEnd.Day Then
                differenceInDay = DateEnd.Day - DateStart.Day
            Else
    
                myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1)
                If differenceInMonth <> 0 Then
                    differenceInMonth -= 1
                Else
                    differenceInMonth = 11
                    differenceInYear -= 1
                End If
    
                differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day
    
            End If
    
            prop_DifferenceInDay = differenceInDay
            prop_DifferenceInMonth = differenceInMonth
            prop_DifferenceInYear = differenceInYear
    
            Return Me
        End Function
    
        Public ReadOnly Property DifferenceInDay() As Integer
            Get
                Return prop_DifferenceInDay
            End Get
        End Property
    
        Public ReadOnly Property DifferenceInMonth As Integer
            Get
                Return prop_DifferenceInMonth
            End Get
        End Property
    
        Public ReadOnly Property DifferenceInYear As Integer
            Get
                Return prop_DifferenceInYear
            End Get
        End Property
    
    End Class
    
    ответ дан Mohammad Ali , с репутацией 11, 14.08.2011
  • 1 рейтинг

    Я написал функцию для достижения этой цели, потому что другие способы не работали для меня.

    public string getEndDate (DateTime startDate,decimal monthCount)
    {
        int y = startDate.Year;
        int m = startDate.Month;
    
        for (decimal  i = monthCount; i > 1; i--)
        {
            m++;
            if (m == 12)
            { y++;
                m = 1;
            }
        }
        return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString());
    }
    
    ответ дан reza akhlaghi, с репутацией 370, 30.09.2013
  • 1 рейтинг
    public static int PayableMonthsInDuration(DateTime StartDate, DateTime EndDate)
    {
        int sy = StartDate.Year; int sm = StartDate.Month; int count = 0;
        do
        {
            count++;if ((sy == EndDate.Year) && (sm >= EndDate.Month)) { break; }
            sm++;if (sm == 13) { sm = 1; sy++; }
        } while ((EndDate.Year >= sy) || (EndDate.Month >= sm));
        return (count);
    }
    

    Это решение для расчета аренды / подписки, где разница не означает вычитание, а промежуток между этими двумя датами.

    ответ дан Sukanta, с репутацией 38, 12.02.2013
  • 1 рейтинг

    Вот гораздо более краткое решение с использованием VB. Net DateDiff только для года, месяца, дня. Вы также можете загрузить библиотеку DateDiff в C #.

    дата1 должна быть & lt; = дата2

    VB. NET

    Dim date1 = Now.AddDays(-2000)
    Dim date2 = Now
    Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0)
    Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0)
    Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day))
    

    C #

    DateTime date1 = Now.AddDays(-2000);
    DateTime date2 = Now;
    int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0;
    int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0;
    int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day);
    
    ответ дан Brent, с репутацией 774, 29.04.2016
  • 1 рейтинг

    Это ответ на вопрос Кирка Волля. У меня недостаточно очков репутации, чтобы ответить на комментарий. , ,

    Мне понравилось решение Кирка, и я собирался бесстыдно сорвать его и использовать в своем коде, но когда я просмотрел его, я понял, что это слишком сложно. Ненужные переключения и циклы, а также открытый конструктор, который бессмысленно использовать.

    Вот мой переписать:

    public class DateTimeSpan {
        private DateTime _date1;
        private DateTime _date2;
        private int _years;
        private int _months;
        private int _days;
        private int _hours;
        private int _minutes;
        private int _seconds;
        private int _milliseconds;
    
        public int Years { get { return _years; } }
        public int Months { get { return _months; } }
        public int Days { get { return _days; } }
        public int Hours { get { return _hours; } }
        public int Minutes { get { return _minutes; } }
        public int Seconds { get { return _seconds; } }
        public int Milliseconds { get { return _milliseconds; } }
    
        public DateTimeSpan(DateTime date1, DateTime date2) {
            _date1 = (date1 > date2) ? date1 : date2;
            _date2 = (date2 < date1) ? date2 : date1;
    
            _years = _date1.Year - _date2.Year;
            _months = (_years * 12) + _date1.Month - _date2.Month;
            TimeSpan t = (_date2 - _date1);
            _days = t.Days;
            _hours = t.Hours;
            _minutes = t.Minutes;
            _seconds = t.Seconds;
            _milliseconds = t.Milliseconds;
    
        }
    
        public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
            return new DateTimeSpan(date1, date2);
        }
    }
    

    Использование1, почти то же самое:

    void Main()
    {
        DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
        DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
        var dateSpan = new DateTimeSpan(compareTo, now);
        Console.WriteLine("Years: " + dateSpan.Years);
        Console.WriteLine("Months: " + dateSpan.Months);
        Console.WriteLine("Days: " + dateSpan.Days);
        Console.WriteLine("Hours: " + dateSpan.Hours);
        Console.WriteLine("Minutes: " + dateSpan.Minutes);
        Console.WriteLine("Seconds: " + dateSpan.Seconds);
        Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
    }
    

    Использование2, аналогично:

    void Main()
    {
        DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
        DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
        Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years);
        Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months);
        Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days);
        Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours);
        Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes);
        Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds);
        Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds);
    }
    
    ответ дан John A, с репутацией 57, 21.04.2017
  • 1 рейтинг

    Это из моей собственной библиотеки, будет возвращать разницу месяцев между двумя датами.

    public static int MonthDiff(DateTime d1, DateTime d2)
    {
        int retVal = 0;
    
        // Calculate the number of years represented and multiply by 12
        // Substract the month number from the total
        // Substract the difference of the second month and 12 from the total
        retVal = (d1.Year - d2.Year) * 12;
        retVal = retVal - d1.Month;
        retVal = retVal - (12 - d2.Month);
    
        return retVal;
    }
    
    ответ дан Wayne, с репутацией 19, 24.04.2012
  • 1 рейтинг

    В моем случае требуется рассчитать полный месяц от даты начала до дня, предшествующего этому дню в следующем месяце, или от начала до конца месяца.


    Пример: с 1 января по 31 января 2008 года - полный месяц
    Пример 2: с 1 мая 2008 года по 2 апреля 2008 года - полный месяц

    , так что на основе этого вот мое решение:

    public static DateTime GetMonthEnd(DateTime StartDate, int MonthsCount = 1)
    {
        return StartDate.AddMonths(MonthsCount).AddDays(-1);
    }
    public static Tuple CalcPeriod(DateTime StartDate, DateTime EndDate)
    {
        int MonthsCount = 0;
        Tuple Period;
        while (true)
        {
            if (GetMonthEnd(StartDate) > EndDate)
                break;
            else
            {
                MonthsCount += 1;
                StartDate = StartDate.AddMonths(1);
            }
        }
        int RemainingDays = (EndDate - StartDate).Days + 1;
        Period = new Tuple(MonthsCount, RemainingDays);
        return Period;
    }
    

    Использование:

    Tuple Period = CalcPeriod(FromDate, ToDate);
    

    Примечание: в моем случае требовалось рассчитать оставшиеся дни после полных месяцев, поэтому, если это не ваш случай, вы можете проигнорировать результат дней или даже изменить метод return с кортежа на целое число.

    ответ дан Ahmed, с репутацией 121, 13.02.2018
  • 1 рейтинг

    Мое понимание общей разницы в месяцах между двумя датами имеет целую и дробную части (дата имеет значение).

    Неотъемлемой частью является полная месячная разница.

    Дробная часть для меня - это разница в процентах от дня (до полных дней месяца) между начальным и конечным месяцами.

    public static class DateTimeExtensions
    {
        public static double TotalMonthsDifference(this DateTime from, DateTime to)
        {
            //Compute full months difference between dates
            var fullMonthsDiff = (to.Year - from.Year)*12 + to.Month - from.Month;
    
            //Compute difference between the % of day to full days of each month
            var fractionMonthsDiff = ((double)(to.Day-1) / (DateTime.DaysInMonth(to.Year, to.Month)-1)) -
                ((double)(from.Day-1)/ (DateTime.DaysInMonth(from.Year, from.Month)-1));
    
            return fullMonthsDiff + fractionMonthsDiff;
        }
    }
    

    С этим расширением, это результаты:

    2/29/2000 TotalMonthsDifference 2/28/2001 => 12
    2/28/2000 TotalMonthsDifference 2/28/2001 => 12.035714285714286
    01/01/2000 TotalMonthsDifference 01/16/2000 => 0.5
    01/31/2000 TotalMonthsDifference 01/01/2000 => -1.0
    01/31/2000 TotalMonthsDifference 02/29/2000 => 1.0
    01/31/2000 TotalMonthsDifference 02/28/2000 => 0.9642857142857143
    01/31/2001 TotalMonthsDifference 02/28/2001 => 1.0
    
    ответ дан George Mavritsakis, с репутацией 5451, 2.10.2015
  • 1 рейтинг

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

    namespace System
    {
         public static class DateTimeExtensions
         {
             public static Int32 DiffMonths( this DateTime start, DateTime end )
             {
                 Int32 months = 0;
                 DateTime tmp = start;
    
                 while ( tmp < end )
                 {
                     months++;
                     tmp = tmp.AddMonths( 1 );
                 }
    
                 return months;
            }
        }
    }
    

    Использование:

    Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) );
    

    Вы можете создать другой метод с именем DiffYears и применить точно такую ​​же логику, что и выше, и AddYears вместо AddMonths в цикле while.

    ответ дан Morgs, с репутацией 663, 29.08.2016
  • 1 рейтинг

    Вы можете иметь функцию, подобную этой.

    Например, с 2012/12/27 по 2012/12/29 становится 3 дня. Аналогичным образом, с 2012/12/15 по 2013/15/15 становится 2 месяца, потому что до 2013/01/14 это 1 месяц. с 15го месяца начался 2й месяц

    Вы можете удалить «=» во втором условии if, если вы не хотите включать в расчет оба дня. я. е, с 2012/12/15 по 2013/15/15 составляет 1 месяц.

    public int GetMonths(DateTime startDate, DateTime endDate)
    {
        if (startDate > endDate)
        {
            throw new Exception("Start Date is greater than the End Date");
        }
    
        int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month);
    
        if (endDate.Day >= startDate.Day)
        {
            months++;
        }
    
        return months;
    }
    
    ответ дан Firnas, с репутацией 795, 27.12.2012
  • 1 рейтинг

    Есть 3 случая: тот же год, предыдущий год и другие годы.

    Если день месяца не имеет значения. , ,

    public int GetTotalNumberOfMonths(DateTime start, DateTime end)
    {
        // work with dates in the right order
        if (start > end)
        {
            var swapper = start;
            start = end;
            end = swapper;
        }
    
        switch (end.Year - start.Year)
        {
            case 0: // Same year
                return end.Month - start.Month;
    
            case 1: // last year
                return (12 - start.Month) + end.Month;
    
            default:
                return 12 * (3 - (end.Year - start.Year)) + (12 - start.Month) + end.Month;
        }
    }
    
    ответ дан Patrice Calvé, с репутацией 494, 16.10.2013
  • 1 рейтинг

    вы можете использовать следующее расширение: код

    public static class Ext
    {
        #region Public Methods
    
        public static int GetAge(this DateTime @this)
        {
            var today = DateTime.Today;
            return ((((today.Year - @this.Year) * 100) + (today.Month - @this.Month)) * 100 + today.Day - @this.Day) / 10000;
        }
    
        public static int DiffMonths(this DateTime @from, DateTime @to)
        {
            return (((((@to.Year - @from.Year) * 12) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 100);
        }
    
        public static int DiffYears(this DateTime @from, DateTime @to)
        {
            return ((((@to.Year - @from.Year) * 100) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 10000;
        }
    
        #endregion Public Methods
    }
    

    Реализация!

    int Age;
    int years;
    int Months;
    //Replace your own date
    var d1 = new DateTime(2000, 10, 22);
    var d2 = new DateTime(2003, 10, 20);
    //Age
    Age = d1.GetAge();
    Age = d2.GetAge();
    //positive
    years = d1.DiffYears(d2);
    Months = d1.DiffMonths(d2);
    //negative
    years = d2.DiffYears(d1);
    Months = d2.DiffMonths(d1);
    //Or
    Months = Ext.DiffMonths(d1, d2);
    years = Ext.DiffYears(d1, d2); 
    
    ответ дан Waleed A.K., с репутацией 898, 22.10.2015
  • 1 рейтинг

    На этот вопрос не так много четких ответов, потому что вы всегда предполагаете что-то.

    Это решение вычисляет между двумя датами месяцы между предположением, что вы хотите сохранить день месяца для сравнения (это означает, что день месяца учитывается при расчете)

    Например, если у вас дата 30 января 2012 года, 29 февраля 2012 года будет не месяцем, а 01 марта 2013 года.

    Это было проверено довольно тщательно, вероятно, будет очищать его позже, когда мы его используем, но здесь:

    private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
    {
        int intReturn = 0;
        bool sameMonth = false;
    
        if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
            intReturn--;
    
        int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days
        int daysinMonth = 0; //used to caputre how many days are in the month
    
        while (dtOther.Date > dtThis.Date) //while Other date is still under the other
        {
            dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
            daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month
    
            if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
            {
                if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month
                    dtThis.AddDays(daysinMonth - dtThis.Day);
                else
                    dtThis.AddDays(dayOfMonth - dtThis.Day);
            }
            if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
            {
                if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
                    intReturn++;
                sameMonth = true; //sets this to cancel out of the normal counting of month
            }
            if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month)
                intReturn++;
        }
        return intReturn; //return month
    }
    
    ответ дан GreatNate, с репутацией 131, 7.01.2014
  • 0 рейтинг

    Чтобы вычислить разницу между двумя датами в месяцах, это вполне логичная вещь, которая необходима во многих бизнес-приложениях. Несколько кодеров, которые предоставили комментарии, такие как - какая разница в месяцах между «май 1,2010» и «16,2010 июня», какая разница в месяцах между 31 декабря 2010 года и 1 января 2011 года? - не смогли понять самые основы бизнес-приложений.

    Вот ответ на вышеуказанные 2 комментария - Количество месяцев между 1 мая 2010 года и 16 июня 2010 года составляет 1 месяц, количество месяцев между 31 декабря 2010 года и 1 января 2011 года равно 0. Было бы очень глупо рассчитывать их как 1. 5 месяцев и 1 секунда, как предложили кодеры выше.

    Люди, которые работали над кредитной картой, обработкой ипотеки, обработкой налогов, обработкой арендной платы, ежемесячными расчетами процентов и множеством других бизнес-решений, согласились бы с этим.

    Проблема в том, что такая функция не включена в C # или VB. NET в этом отношении. Datediff учитывает только годы или компонент месяца, поэтому фактически бесполезен.

    Вот несколько реальных примеров того, как вам нужно и как правильно рассчитать месяцы:

    Вы жили в краткосрочной аренде с 18 февраля по 23 августа. Сколько месяцев вы там пробыли? Ответ прост - 6 месяцев

    У вас есть банковский счет, на котором проценты начисляются и выплачиваются в конце каждого месяца. Вы вносите деньги 10 июня и снимаете их 29 октября (в том же году). Сколько месяцев вы интересуетесь? Очень простой ответ - 4 месяца (опять лишние дни не имеют значения)

    В бизнес-приложениях большую часть времени, когда вам нужно вычислять месяцы, это происходит потому, что вам нужно знать «полные» месяцы на основе того, как люди вычисляют время; не основанный на некоторых абстрактных / не относящихся к делу мыслях.

    ответ дан Tom, с репутацией 33, 11.06.2012
  • 0 рейтинг
      var dt1 = (DateTime.Now.Year * 12) + DateTime.Now.Month;
      var dt2 = (DateTime.Now.AddMonths(-13).Year * 12) + DateTime.Now.AddMonths(-13).Month;
      Console.WriteLine(dt1);
      Console.WriteLine(dt2);
      Console.WriteLine((dt1 - dt2));
    
    ответ дан Paul, с репутацией 1, 23.01.2014
  • 0 рейтинг

    Расширенная структура Киркс с ToString (формат) и продолжительностью (длинная мс)

     public struct DateTimeSpan
    {
        private readonly int years;
        private readonly int months;
        private readonly int days;
        private readonly int hours;
        private readonly int minutes;
        private readonly int seconds;
        private readonly int milliseconds;
    
        public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
        {
            this.years = years;
            this.months = months;
            this.days = days;
            this.hours = hours;
            this.minutes = minutes;
            this.seconds = seconds;
            this.milliseconds = milliseconds;
        }
    
        public int Years { get { return years; } }
        public int Months { get { return months; } }
        public int Days { get { return days; } }
        public int Hours { get { return hours; } }
        public int Minutes { get { return minutes; } }
        public int Seconds { get { return seconds; } }
        public int Milliseconds { get { return milliseconds; } }
    
        enum Phase { Years, Months, Days, Done }
    
    
        public string ToString(string format)
        {
            format = format.Replace("YYYY", Years.ToString());
            format = format.Replace("MM", Months.ToString());
            format = format.Replace("DD", Days.ToString());
            format = format.Replace("hh", Hours.ToString());
            format = format.Replace("mm", Minutes.ToString());
            format = format.Replace("ss", Seconds.ToString());
            format = format.Replace("ms", Milliseconds.ToString());
            return format;
        }
    
    
        public static DateTimeSpan Duration(long ms)
        {
            DateTime dt = new DateTime();
            return CompareDates(dt, dt.AddMilliseconds(ms));
        }
    
    
        public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
        {
            if (date2 < date1)
            {
                var sub = date1;
                date1 = date2;
                date2 = sub;
            }
    
            DateTime current = date1;
            int years = 0;
            int months = 0;
            int days = 0;
    
            Phase phase = Phase.Years;
            DateTimeSpan span = new DateTimeSpan();
    
            while (phase != Phase.Done)
            {
                switch (phase)
                {
                    case Phase.Years:
                        if (current.AddYears(years + 1) > date2)
                        {
                            phase = Phase.Months;
                            current = current.AddYears(years);
                        }
                        else
                        {
                            years++;
                        }
                        break;
                    case Phase.Months:
                        if (current.AddMonths(months + 1) > date2)
                        {
                            phase = Phase.Days;
                            current = current.AddMonths(months);
                        }
                        else
                        {
                            months++;
                        }
                        break;
                    case Phase.Days:
                        if (current.AddDays(days + 1) > date2)
                        {
                            current = current.AddDays(days);
                            var timespan = date2 - current;
                            span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
                            phase = Phase.Done;
                        }
                        else
                        {
                            days++;
                        }
                        break;
                }
            }
    
            return span;
        }
    }
    
    ответ дан Ivan, с репутацией 106, 6.12.2013
  • 0 рейтинг

    Вот как мы подходим к этому:

    public static int MonthDiff(DateTime date1, DateTime date2)
    {
        if (date1.Month < date2.Month)
        {
            return (date2.Year - date1.Year) * 12 + date2.Month - date1.Month;
        }
        else
        {
            return (date2.Year - date1.Year - 1) * 12 + date2.Month - date1.Month + 12;
        }
    }
    
    ответ дан Konstantin Chernov, с репутацией 1284, 21.01.2015
  • 0 рейтинг
    int nMonths = 0;
    if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
         nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;                         
    else
    nMonths = (12 - FDate.Month) + TDate.Month;                          
    
    ответ дан Bhavesh Patel, с репутацией 1, 12.06.2015
  • 0 рейтинг

    Простое исправление. Работает 100%

            var exactmonth = (date1.Year - date2.Year) * 12 + date1.Month - 
            date2.Month +  (date1.Day >= date2.Day ? 0 : -1);
            Console.WriteLine(exactmonth);
    
    ответ дан Shahnawaz Alam, с репутацией 89, 1.06.2018
  • -2 рейтинг

    LINQ Solution,

    DateTime ToDate = DateTime.Today;
    DateTime FromDate = ToDate.Date.AddYears(-1).AddDays(1);
    
    int monthCount = Enumerable.Range(0, 1 + ToDate.Subtract(FromDate).Days)
                        .Select(x => FromDate.AddDays(x))
                        .ToList()
                        .GroupBy(z => new { z.Year, z.Month })
                        .Count();
    
    ответ дан Chethaka Wickramarathne, с репутацией 1, 10.08.2016