如何在c#中计算两个日期之间的月差?

c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:

TimeSpan ts = date1 - date2;

但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。

有什么建议吗?


当前回答

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

其他回答

扩展的Kirks结构与ToString(格式)和持续时间(长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;
    }
}

要获得月份的差异(包括开始和结束),而不考虑日期:

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

如果你只关心月份和年份,想要触及两个日期(例如你想要从JAN/2021到AGO/2022),你可以使用这个:

int numberOfMonths= (Year2 > Year1 ? ( Year2 - Year1 - 1) * 12 + (12 - Month1) + Month2 + 1 : Month2 - Month1 + 1); 

例子:

Year1/Month1: 2021/10   
Year2/Month2: 2022/08   
numberOfMonths = 11;

或者同年:

Year1/Month1: 2021/10   
Year2/Month2: 2021/12   
numberOfMonths = 3;

如果你只想触碰其中一个,就去掉两个+ 1。

这里有一个简单的解决方案,至少对我来说是有效的。它可能不是最快的,因为它在循环中使用了很酷的DateTime的AddMonth功能:

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

我们是这样做的:

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