计算两个日期之间的小数月数(C#)

时间:2011-07-02 09:48:29

标签: c# .net

我想要两天之间(可能是分数)日历月的数量,例如2013年1月2日 - 2014年2月15日应为12.5个月左右。

我很惊讶没有发现谷歌已经回复了这个问题。

编辑:我最后编写了一些代码 - 如果有人需要相同的话,这是我的答案(我当天的好事):

/// <summary>
/// Number of total calendar months between two dates. If day of month is different,
/// gives fractional approximation using average days per month.
/// </summary>
public static double MonthsBetween(DateTime start, DateTime finish)
{
    //handle if dates switched - calculation same but there's a negative result:
    double multiplier;
    if(finish < start)
    {
        var temp = start;
        start = finish;
        finish = temp;
        multiplier = -1;
    }
    else
    {
        multiplier = 1;
    }

    //1) 20 Mar 2012 - 13 Jan 2014 --> 2*12 months
    //2) 15 Jan 2011 - 30 Jul 2012 --> 1*12 months
    //3) 20 Jan 2010 - 25 Jan 2010 --> 0*12 months
    double totalMonths = (finish.Year - start.Year)*12;

    //1) 20 Mar 2012 - 13 Jan 2014 --> 2*12 + 1 - 3 = 22 months
    //2) 15 Jan 2011 - 30 Jul 2012 --> 1*12 + 7 - 1 = 18 months
    //3) 20 Jan 2010 - 25 Jan 2010 --> 0*12 + 0 months = 0 months
    totalMonths += finish.Month - start.Month;

    ///Now we have "1st of the month to 1st of the month" difference. Days can only be approximated,
    ///since each month has a different number of days. Statistically (http://en.wikipedia.org/wiki/Month#Julian_and_Gregorian_calendars):
    const double averageDaysInMonth = 30.436875;

    ///Remove the days we've included in the starting month (not in actual period):
    totalMonths -= start.Day / averageDaysInMonth;

    ///Add the days in the finish month (weren't yet included, since had "1st to 1st"):
    totalMonths += finish.Day / averageDaysInMonth;

    //1) 20 Mar 2012 - 13 Jan 2014 --> 2*12 + 1 - 3 - 20/30 + 13/30 = 22 - 7/30 = 21.76 months
    //2) 15 Jan 2011 - 30 Jul 2012 --> 1*12 + 7 - 1 - 15/30 + 30/30 = 18 + 15/30 = 18.5 months
    //3) 20 Jan 2010 - 25 Jan 2010 --> 0*12 + 0 - 20/30 + 25/30 = 0 + 5/30 = 0.17 months

    return totalMonths * multiplier;
}

同样,我在多年后需要类似的东西后才意识到。这也是代码,如果有人帮助的话:

/// <summary>
/// Number of total calendar years between two dates. Gives fractional 
/// approximation if months/days differ.
/// </summary>
public static double YearsBetween(DateTime start, DateTime finish)
{
    //handle if dates switched - calculation same but there's a negative result:
    double multiplier;
    if (finish < start)
    {
        var temp = start;
        start = finish;
        finish = temp;
        multiplier = -1;
    }
    else
    {
        multiplier = 1;
    }

    //1) 20 Mar 2012 - 13 Jan 2014 --> 2 years
    //2) 15 Jan 2011 - 30 Jul 2012 --> 1 year
    //3) 20 Jan 2010 - 25 Jan 2010 --> 0 years
    double totalYears = finish.Year - start.Year;

    ///Now we have "1st of the year to 1st of the year" difference. Days/months can only be approximated,
    ///since each year has a different number of days. Statistically (http://en.wikipedia.org/wiki/Year):
    const double averageDaysPerYear = 365.2425;

    ///Remove the days we've included in the starting year (not in actual period):
    totalYears -= start.DayOfYear / averageDaysPerYear;

    ///Add the days in the finish year (weren't yet included, since had "Jan 1 to Jan 1"):
    totalYears += finish.DayOfYear / averageDaysPerYear;

    //1) 20 Mar 2012 - 13 Jan 2014 --> 2 - ~(2*30+20)/365 + 13/365 = 1.82 years
    //2) 15 Jan 2011 - 30 Jul 2012 --> 1 - 15/365 + ~(6*30+30)/365 = 1.53 years
    //3) 20 Jan 2010 - 25 Jan 2010 --> 0 - 20/365 + 25/365 = 0.01 years

    return totalYears * multiplier;
}

5 个答案:

答案 0 :(得分:1)

可能是使用假设的最佳选择;

var startTime = Convert.ToDateTime("02/01/2013");
var endTime = Convert.ToDateTime("15/02/2014");
var span = endTime.Subtract(startTime);

Console.WriteLine("Time Difference (months): " + Math.Round((decimal)span.Days/30,1));

提供13.6

答案 1 :(得分:1)

使用以下内容:

TimeSpan timeSpan = laterDate.Subtract(earlierDate);
var monthsCount = timeSpan.TotalDays / MonthDaysCount;

答案 2 :(得分:0)

如果你真的想要分数月,那么一种方法是花费天数并除以一个月内的(近似)平均天数。

e.g。

(new DateTime(2013, 1, 2) - new DateTime(2014, 2, 15)).TotalDays / (365.25 / 12)

结果为-13.4373716632444。这可以四舍五入到您需要的精度,例如13.5(我相信你问题中的12.5应该是13.5)。

这里的近似值是一个月中的平均天数365.25 / 12.这应该适用于所有但非常大的日期范围。

修改

然而,重要的是要注意这是一个近似值 - 日历月是不一致的度量(天数变化),因此一个月的一半不一定等于另一个月的一半。

鉴于此,a)每个日历月收费并制定政策,如果服务提供15天或更长时间,或b)按天收费,您将收取指定月份的费用。如果你真的想要降到'半月'水平,那么你需要决定标准的'半月'何时过去,例如15天,但在决定何时应该收取下一个“半月”的时候会变得复杂。

答案 3 :(得分:0)

如果您愿意使用30天的月份,请尝试以下操作:

DateTime date1 = new DateTime(2013, 1, 2);
DateTime date2 = new DateTime(2014, 2, 15);

TimeSpan difference = date2.Subtract(date1);

double elapsedMonths = difference.TotalDays / 30;

答案 4 :(得分:0)

如果您每月收费而不仅仅是Math.Floor不收取这些额外的几天。您的客户会很高兴,甚至可能会回来(或至少告诉其他潜在客户)。

另外,你已经解决这个问题的时间可能少于你将要放弃的金额......