Différence en mois entre deux dates

comment calculer la différence en mois entre deux dates en C#?

il Est équivalent de VB DateDiff() méthode en C#. Je dois trouver une différence en mois entre deux dates qui sont à des années d'intervalle. La documentation dit que je peux utiliser TimeSpan comme:

TimeSpan ts = date1 - date2;

mais cela me donne des données en jours. Je ne veux pas diviser ce nombre par 30 parce que pas tous les mois est de 30 jours et depuis les deux les valeurs opérandes sont très différentes les unes des autres, je crains que diviser par 30 puisse me donner une mauvaise valeur.

des suggestions?

269
demandé sur John Saunders 2011-01-09 14:59:57

30 réponses

en supposant que le jour du mois n'est pas pertinent (c.-à-d. la différence entre 2011.1.1 et 2010.12.31 est 1), avec date1 > date2 donnant une valeur positive et date2 > date1 une valeur négative

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

Ou, en supposant que vous voulez un nombre approximatif de la moyenne des mois entre les deux dates, la suivante devrait fonctionner pour tous, mais très grand jour les différences.

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

Note, Si vous deviez utiliser cette dernière solution, alors votre unité teste devrait indiquer la plage de date la plus large que votre application est conçue pour travailler avec et valider les résultats du calcul en conséquence.


mise à Jour (merci à Gary )

si l'on utilise la méthode des "mois moyens", un nombre légèrement plus précis à utiliser pour le "nombre moyen de jours par année" est 365.2425 .

362
répondu Adam Ralph 2017-09-03 07:56:18

Voici une solution complète pour retourner un DateTimeSpan , semblable à un TimeSpan , sauf qu'il comprend tous les composants de date en plus des composants de temps.

Utilisation:

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

sorties:

Années: 1

Mois: 5

Jours: 27

Heures: 1

Minutes: 36

Secondes: 50

Millisecondes: 0

pour plus de commodité, j'ai regroupé la logique dans la structure DateTimeSpan , mais vous pouvez déplacer la méthode CompareDates où que vous le vouliez. Notez aussi que peu importe quelle date vient avant l'autre.

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;
    }
}
191
répondu Kirk Woll 2016-04-02 21:44:12

si vous voulez le nombre exact de mois complets, toujours positif (2000-01-15, 2000-02-14 retours 0), considérant un mois complet est quand vous atteignez le même jour le mois suivant (quelque chose comme le calcul de l'âge)

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

modifier raison: l'ancien code n'était pas correct dans certains cas comme:

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 },
};
31
répondu Guillaume86 2018-03-03 07:10:35

Vous pourriez le faire

if ( date1.AddMonths(x) > date2 )
27
répondu Mongus Pong 2011-09-20 16:36:26

j'ai vérifié l'utilisation de cette méthode dans VB.NET via MSDN et il semble qu'il ait beaucoup d'usages. Il n'existe pas une méthode intégrée dans C#. (Même si ce n'est pas une bonne idée) vous pouvez appeler VB dans C#.

  1. ajouter Microsoft.VisualBasic.dll à votre projet comme référence
  2. utilisation Microsoft.VisualBasic.DateAndTime.DateDiff dans votre code
22
répondu Danny Chen 2011-01-09 12:19:41

pour obtenir la différence en mois (début et fin inclus), indépendamment des dates:

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);
9
répondu Chirag 2014-12-19 10:44:40

j'avais juste besoin de quelque chose de simple pour répondre aux dates d'emploi par exemple où seulement le mois/année est entré, donc voulu des années distinctes et des mois travaillés. C'est ce que j'utilise, ici, pour l'utilité seulement

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

. violon net

6
répondu jenson-button-event 2018-03-03 17:13:50

vous pouvez utiliser la classe DateDiff de la bibliothèque Time Period Library for .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
4
répondu 2014-04-05 08:09:29

Utiliser Noda Temps :

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

(exemple de source)

3
répondu Edward Brey 2017-05-23 12:02:46

cela a fonctionné pour ce que j'en avais besoin. Le jour du mois n'a pas d'importance dans mon cas, car il arrive toujours à être le dernier jour du mois.

public static int MonthDiff(DateTime d1, DateTime d2){
    int retVal = 0;

    if (d1.Month<d2.Month)
    {
        retVal = (d1.Month + 12) - d2.Month;
        retVal += ((d1.Year - 1) - d2.Year)*12;
    }
    else
    {
        retVal = d1.Month - d2.Month;
        retVal += (d1.Year - d2.Year)*12;
    }
    //// 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;
}
2
répondu Elmer 2018-03-03 04:16:03

le moyen le plus précis est celui qui retourne différence en mois par fraction:

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;
}
2
répondu Saeed Mahmoudi 2018-03-03 09:50:40

Voici une solution simple qui fonctionne au moins pour moi. Ce n'est probablement pas le plus rapide car il utilise la fonction AddMonth de cool DateTime dans une boucle:

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);
}
2
répondu Simon Mourier 2018-03-04 07:55:47
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
1
répondu Mohammad Ali 2011-08-14 14:16:37

c'est de ma propre bibliothèque, vous retournera la différence de mois entre deux dates.

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;
}
1
répondu Wayne 2012-04-25 13:25:09

vous pouvez avoir une fonction de ce genre.

par exemple, du 2012/12/27 au 2012/12/29 devient 3 jours. De même, du 15/12/2012 au 15/01/2013 devient 2 mois, parce que jusqu'au 14/01/2013 c'est 1 mois. à partir du 15 c'est la 2ème mois commencé.

Vous pouvez supprimer le "=" dans la deuxième condition si, si vous ne souhaitez pas inclure les deux jours dans le calcul. I. e, du 15/12/2012 au 15/01/2013 est de 1 mois.

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;
}
1
répondu Firnas 2012-12-27 10:43:41

vous pouvez utiliser l'extension suivante: Code

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
}

la mise en Œuvre !

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); 
1
répondu Waleed A.K. 2015-10-22 18:19:46

Voici une solution beaucoup plus concise en utilisant VB.Net DateDiff pour L'année, le mois, le jour seulement. Vous pouvez également charger la bibliothèque DateDiff dans C#.

date1 doit être < = date2

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);
1
répondu Brent 2016-04-29 14:48:16

Voici ma contribution pour obtenir la différence en Mois que j'ai trouvé pour être précis:

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

Utilisation:

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

vous pouvez créer une autre méthode appelée diff Years et appliquer exactement la même logique que ci-dessus et add years au lieu D'Add months dans la boucle while.

1
répondu Morgs 2016-08-29 09:37:25

C'est en réponse à la réponse de Kirk Woll. Je n'ai pas assez de points de réputation pour répondre à un commentaire encore...

J'ai aimé la solution de Kirk et j'allais sans honte l'arracher et l'utiliser dans mon code, mais quand je l'ai regardé je me suis rendu compte que c'était beaucoup trop compliqué. Commutation inutile et Bouclage, et un constructeur public qui est inutile d'utiliser.

voici ma réécriture:

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

Usage1, pretty à peu près la même chose:

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

Usage2, similaire:

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);
}
1
répondu John A 2017-04-21 15:33:26

dans mon cas, il est nécessaire de calculer le mois complet à partir de la date de début jusqu'au jour précédant ce jour dans le mois suivant ou du début à la fin du mois.



Ex: du 1/1/2018 au 31/1/2018 est un mois complet

Ex2: du 5/1/2018 au 4/2/2018 est un mois complet

sur cette base voici ma solution:

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

Utilisation:

Tuple<int, int> Period = CalcPeriod(FromDate, ToDate);

Note: dans mon cas, il était nécessaire de calculer les jours restants après les mois complets, donc si ce n'est pas votre cas, vous pourriez ignorer le résultat des jours ou même vous pourriez changer la méthode de retour de tuple à Entier.

1
répondu Ahmed 2018-03-03 02:51:05
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);
}

cette solution est pour le calcul de location/abonnement, où la différence ne signifie pas être soustraction, il est censé être la portée dans ces deux dates.

1
répondu Sukanta 2018-03-03 04:10:16

il y a 3 cas: la même année, l'année précédente et d'autres années.

Si le jour du mois n'a pas d'importance...

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;
    }
}
1
répondu Patrice Calvé 2018-03-03 04:16:37

j'ai écrit une fonction pour accomplir ceci, parce que les autres façons ne fonctionnaient pas pour moi.

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());
}
1
répondu reza akhlaghi 2018-03-03 09:27:19

ma compréhension de l'écart total de mois entre 2 dates a une partie intégrante et une partie fractionnaire (la date importe).

la partie intégrante est la différence de mois entiers.

la fraction, pour moi, est la différence du % du jour (aux jours entiers du mois) entre le mois de début et le mois de fin.

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

avec cette extension, ce sont les résultats:

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
1
répondu George Mavritsakis 2018-03-03 17:19:08

il n'y a pas beaucoup de réponses claires à cela parce que vous supposez toujours des choses.

cette solution calcule entre deux dates les mois entre l'hypothèse que vous voulez sauver le jour du mois pour la comparaison, (ce qui signifie que le jour du mois est considéré dans le calcul)

exemple, si vous avez une date du 30 janvier 2012, le 29 février 2012 ne sera pas un mois mais le 1er mars 2013 le sera.

il a été testé joli soigneusement, probablement nettoiera plus tard comme nous l'utilisons, mais ici:

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
}
1
répondu GreatNate 2018-03-03 18:47:23

pour pouvoir calculer la différence entre 2 dates en mois est une chose parfaitement logique à faire, et est nécessaire dans de nombreuses applications d'affaires. Les différents codeurs ici qui ont fourni des commentaires tels que - quelle est la différence en mois entre "mai 12010" et " juin 16,2010, Quelle est la différence en mois entre le 31 décembre 2010 et le 1er janvier 2011? -- n'ont pas compris les bases des applications commerciales.

Ici est la réponse à la ci-dessus 2 commentaires - Le nombre de mois compris entre le 1er mai 2010 et le 16-jun-2010 est de 1 mois, le nombre de mois entre le 31 décembre 2010 et 1er janvier 2011 est de 0. Il serait très stupide de les calculer comme 1,5 mois et 1 seconde, comme les codeurs ci-dessus ont suggéré.

les personnes qui ont travaillé sur les cartes de crédit, le traitement des hypothèques, le traitement des impôts, le traitement des loyers, le calcul des intérêts mensuels et une grande variété d'autres solutions d'affaires seraient d'accord.

problème est qu'une telle fonction n'est pas incluse dans C# ou VB.NET d'ailleurs. Datediff ne prend en compte que les années ou la composante de mois, donc est en fait inutile.

voici quelques exemples concrets d'endroits où vous devez Et pouvez calculer correctement les mois:

vous avez vécu dans une location à court terme du 18 février au 23 août. Combien de mois y êtes-vous resté? La réponse est simple - 6 mois

vous avez un compte bancaire où l'intérêt est calculés et payés à la fin de chaque mois. Vous déposez de l'argent le 10-jun et le retirez le 29-oct (même année). Combien de mois avez-vous susciter l'intérêt? Réponse très simple-4 mois (encore une fois les jours supplémentaires n'ont pas d'importance)

dans les applications d'affaires, la plupart du temps, quand vous avez besoin de calculer des mois, c'est parce que vous avez besoin de savoir "plein" mois basé sur la façon dont les humains calculent le temps; pas basé sur certaines pensées abstraites/non pertinentes.

0
répondu Tom 2012-06-11 17:27:24

Kirks struct élargi avec ToString (format) et la durée(long ms)

 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;
    }
}
0
répondu Ivan 2013-12-06 13:37:52
  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));
0
répondu Paul 2014-01-23 17:42:55

Voici comment nous abordons ceci:

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;
    }
}
0
répondu Konstantin Chernov 2015-01-21 11:57:45
int nMonths = 0;
if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
     nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;                         
else
nMonths = (12 - FDate.Month) + TDate.Month;                          
0
répondu Bhavesh Patel 2015-06-12 07:51:02