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

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

TimeSpan ts = date1 - date2;

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

有什么建议吗?


当前回答

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {

        label3.Text = new DateDifference(Convert.ToDateTime("2018-09-13"), Convert.ToDateTime("2018-11-15")).ToString();
        label2.Text = new DateDifference(Convert.ToDateTime("2018-10-12"), Convert.ToDateTime("2018-11-15")).ToString();

        DateDifference oDateDifference = new DateDifference(Convert.ToDateTime("2018-11-12"));
       label1.Text  =   oDateDifference.ToString();

    }
}




public class DateDifference
{
    public DateTime start { get; set; }
    public DateTime currentDAte { get; set; }
    public DateTime origstart { get; set; }
    public DateTime origCurrentDAte { get; set; }

    int days { get; set; }
    int months { get; set; }
    int years { get; set; }

    public DateDifference(DateTime postedDate, DateTime currentDAte)
    {
        this.start = this.removeTime(postedDate);
        this.currentDAte = this.removeTime(currentDAte);
        this.origstart = postedDate;
        this.origCurrentDAte = currentDAte;

    }

    public DateDifference(DateTime postedDate)
    {
        DateTime currentDate_ = DateTime.Now;
        this.start = this.removeTime(postedDate);
        this.currentDAte = this.removeTime(currentDate_);
        this.origstart = postedDate;
        this.origCurrentDAte = currentDate_;
        if (start > this.currentDAte)
        {
            throw new Exception("Current date is greater than date posted");
        }
        this.compute();
    }

    void compute()
    {
        while (this.start.Year <= this.currentDAte.Year)
        {
            if (this.start.Year <= this.currentDAte.Year && (this.start.AddMonths(1) <= this.currentDAte))
            {
                ++this.months;
                this.start = this.start.AddMonths(1);
            }

            if ((this.start.Year == this.currentDAte.Year) && (this.start >= this.currentDAte.AddMonths(-1) && this.start <= this.currentDAte))
            {
                break;
            }
        }

        while (this.start.DayOfYear < this.currentDAte.DayOfYear)
        {
            ++this.days;
            this.start = start.AddDays(1);
        }

        if (this.months > 11)
        {
            while (this.months > 11)
            {
                ++this.years;
                this.months = months - 12;
            }
        }

    }


    public override string ToString()
    {
        if (this.start > this.currentDAte)
        {
            throw new Exception("Current date is greater than date posted");
        }
        String ret = this.ComposeTostring();
        this.reset();
        return ret;
    }

    private String ComposeTostring()
    {
        this.compute();
        if (this.years > 0)
        {
            if (this.months > 0)
            {
                if (this.days > 0)
                {
                    return String.Format("{0} year{1}, {2} month{3} && {4} Day{5} ago", this.years, plural(this.years), this.months, plural(this.months), this.days, plural(this.days));
                }
                return String.Format("{0} year{1}, {2} month{3} ago", this.years, plural(this.years), this.months, plural(this.months));
            }
            else
            {
                if (this.days > 0)
                {
                    return String.Format("{0} year{1},{2} day{3} ago", this.years, plural(this.years), this.days, plural(this.days));
                }

                return String.Format("{0} year{1} ago", this.years, plural(this.years));

            }
        }

        if (this.months > 0)
        {
            if (this.days > 0)
            {
                return String.Format("{0} month{1}, {2} day{3} ago", this.months, plural(this.months), this.days, plural(this.days));
            }
            else
            {
                return String.Format("{0} month{1} ago", this.months, plural(this.months));
            }
        }

        if ((this.origCurrentDAte - this.origstart).Days > 0)
        {
            int daysDiff = (this.origCurrentDAte - this.origstart).Days;
            this.origstart = this.origstart.AddDays(daysDiff);
            int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
            return String.Format("{0} day{1}, {2} hour{3} ago", daysDiff, plural(daysDiff), HoursDiff, plural(HoursDiff));

        }
        else if ((this.origCurrentDAte - this.origstart).Hours > 0)
        {
            int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
            this.origstart = this.origstart.AddHours(HoursDiff);
            int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
            return String.Format("{0} hour{1}, {2} minute{3} ago", HoursDiff, plural(HoursDiff), MinDiff, plural(MinDiff));
        }
        else if ((this.origCurrentDAte - this.origstart).Minutes > 0)
        {

            int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
            this.origstart = this.origstart.AddMinutes(MinDiff);
            int SecDiff = (this.origCurrentDAte - this.origstart).Seconds;
            return String.Format("{0} minute{1}, {2} second{3} ago", MinDiff, plural(MinDiff), SecDiff, plural(SecDiff));
        }
        else if ((this.origCurrentDAte - this.origstart).Seconds > 0)
        {
            int sec = (this.origCurrentDAte - this.origstart).Seconds;
            return String.Format("{0} second{1}", sec, plural(sec));
        }

        return "";
    }

    String plural(int val)
    {
        return (val > 1 ? "s" : String.Empty);
    }

    DateTime removeTime(DateTime dtime)
    {
        dtime = dtime.AddHours(-dtime.Hour);
        dtime = dtime.AddMinutes(-dtime.Minute);
        dtime = dtime.AddSeconds(-dtime.Second);
        return dtime;
    }

    public void reset()
    {

        this.days = 0;
        this.months = 0;
        this.years = 0;
        this.start = DateTime.MinValue;
        this.currentDAte = DateTime.MinValue;
        this.origstart = DateTime.MinValue;
        this.origCurrentDAte = DateTime.MinValue;
    }
}

其他回答

简单快速的解决方案,计算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;
        }

我在VB中检查了这个方法的用法。NET通过MSDN,它似乎有很多用途。c#中没有这样的内置方法。(即使这不是一个好主意)你可以在c#中调用VB。

将Microsoft.VisualBasic.dll添加到 你的项目作为参考 使用 Microsoft.VisualBasic.DateAndTime.DateDiff 在代码中

你可以这样做

if ( date1.AddMonths(x) > date2 )

你可以使用野田时间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);

使用野田时间:

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

(例子)