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

本文关键字:小数 日期 两个 计算 之间 | 更新日期: 2023-09-27 18:00:51

我希望两天之间的日历月数(可能是小数(,例如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;
}

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

使用以下内容:

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

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

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

如果你愿意每月使用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;

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

例如

(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天,但在决定下一个"半"月何时收费时,这会变得复杂。

如果你每月收费,而不仅仅是Math.Floor,那么就不要对额外的几天收费。你的客户会很高兴地感到惊讶,甚至可能会回来(或者至少告诉其他一些潜在客户(。

此外,你已经花在解决这个问题上的时间可能少于你将要花的钱。。。