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

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

TimeSpan ts = date1 - date2;

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

有什么建议吗?


当前回答

一定是有人干的))

扩展方法返回给定日期之间的完整月数。无论以什么顺序接收日期,都会返回一个自然数。在“正确”答案中没有近似的计算。

    /// <summary>
    /// Returns the difference between dates in months.
    /// </summary>
    /// <param name="current">First considered date.</param>
    /// <param name="another">Second considered date.</param>
    /// <returns>The number of full months between the given dates.</returns>
    public static int DifferenceInMonths(this DateTime current, DateTime another)
    {
        DateTime previous, next;
        if (current > another)
        {
            previous = another;
            next     = current;
        }
        else
        {
            previous = current;
            next     = another;
        }

        return
            (next.Year - previous.Year) * 12     // multiply the difference in years by 12 months
          + next.Month - previous.Month          // add difference in months
          + (previous.Day <= next.Day ? 0 : -1); // if the day of the next date has not reached the day of the previous one, then the last month has not yet ended
    }

但如果你仍然想要得到月份的小数部分,你只需要在回报中再加一项:

+(下一个。Day - previous.Day) / DateTime.DaysInMonth(previous. Day)年,previous.Month)

其他回答

假设这个月的日期不相关(即2011.1.1和2010.12.31之间的差为1),date1 > date2为正值,date2 > date1为负值

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

或者,假设你想要两个日期之间的“平均月”的大致数字,下面的方法应该适用于所有日期,但日期差异非常大。

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

注意,如果您要使用后一种解决方案,那么您的单元测试应该声明应用程序设计使用的最宽日期范围,并相应地验证计算结果。


更新(感谢Gary)

如果使用“平均月份”方法,“每年平均天数”的更准确数字是365.2425。

简单快速的解决方案,计算2个日期之间的总月份。 如果你只想得到不同的月份,而不计算From date中的月份-只需从代码中删除+1。

public static int GetTotalMonths(DateTime From, DateTime Till)
        {
            int MonthDiff = 0;

            for (int i = 0; i < 12; i++)
            {
                if (From.AddMonths(i).Month == Till.Month)
                {
                    MonthDiff = i + 1;
                    break;
                }
            }

            return MonthDiff;
        }

你可以使用野田时间https://nodatime.org/

LocalDate start = new LocalDate(2010, 1, 5);
LocalDate end = new LocalDate(2012, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months);

你可以有一个这样的函数。

例如,从2012/12/27到2012/12/29变成3天。同样,从2012/12/15到2013/01/15变成了2个月,因为到2013/01/14是1个月。从15号开始是第二个月。

如果您不想在计算中包括这两天,则可以删除第二个if条件中的“=”。即从2012/12/15到2013/01/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;
}

疯狂的方法,计算所有的日子,超级精确

Helper类:

public class DaysInMonth
{
    public int Days { get; set; }
    public int Month { get; set; }
    public int Year { get; set; }
    public bool Full { get; set; }
}

功能:

    public static List<DaysInMonth> MonthsDelta(DateTime start, DateTime end)
    {
        
        var dates = Enumerable.Range(0, 1 + end.Subtract(start).Days)
          .Select(offset => start.AddDays(offset))
          .ToArray();

        DateTime? prev = null;
        int days = 0;

        List < DaysInMonth > list = new List<DaysInMonth>();

        foreach (DateTime date in dates)
        {
            if (prev != null)
            {
                if(date.Month!=prev.GetValueOrDefault().Month)
                {
                    DaysInMonth daysInMonth = new DaysInMonth();
                    daysInMonth.Days = days;
                    daysInMonth.Month = prev.GetValueOrDefault().Month;
                    daysInMonth.Year = prev.GetValueOrDefault().Year;
                    daysInMonth.Full = DateTime.DaysInMonth(daysInMonth.Year, daysInMonth.Month) == daysInMonth.Days;
                    list.Add(daysInMonth);
                    days = 0;
                }
            }
            days++;
            prev = date;
        }

        //------------------ add last
        if (days > 0)
        {
            DaysInMonth daysInMonth = new DaysInMonth();
            daysInMonth.Days = days;
            daysInMonth.Month = prev.GetValueOrDefault().Month;
            daysInMonth.Year = prev.GetValueOrDefault().Year;
            daysInMonth.Full = DateTime.DaysInMonth(daysInMonth.Year, daysInMonth.Month) == daysInMonth.Days;
            list.Add(daysInMonth);
        }

        return list;
    }