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

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

TimeSpan ts = date1 - date2;

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

有什么建议吗?


当前回答

int nMonths = 0;
if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
     nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;                         
else
nMonths = (12 - FDate.Month) + TDate.Month;                          

其他回答

在我的情况下,需要计算从开始日期到下个月这一天的前一天或从月初到月底的完整月份。

例如:从1/1/2018到31/1/2018是一个完整的月 例2:从5/1/2018到4/2/2018是一个完整的月

基于此,我的解决方案如下:

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

用法:

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

注意:在我的情况下,需要计算完整月份之后的剩余天数,所以如果不是你的情况,你可以忽略天数结果,甚至可以将方法返回值从元组更改为整数。

这里有一个简单的解决方案,至少对我来说是有效的。它可能不是最快的,因为它在循环中使用了很酷的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 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;
    }
}

简单的修复。工作的100%

        var exactmonth = (date1.Year - date2.Year) * 12 + date1.Month - 
        date2.Month +  (date1.Day >= date2.Day ? 0 : -1);
        Console.WriteLine(exactmonth);

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

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