如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
当前回答
我的问题用这个方法解决了:
static void Main(string[] args)
{
var date1 = new DateTime(2018, 12, 05);
var date2 = new DateTime(2019, 03, 01);
int CountNumberOfMonths() => (date2.Month - date1.Month) + 12 * (date2.Year - date1.Year);
var numberOfMonths = CountNumberOfMonths();
Console.WriteLine("Number of months between {0} and {1}: {2} months.", date1.ToString(), date2.ToString(), numberOfMonths.ToString());
Console.ReadKey();
//
// *** Console Output:
// Number of months between 05/12/2018 00:00:00 and 01/03/2019 00:00:00: 3 months.
//
}
其他回答
最精确的方法是以月为单位的分数返回差值:
private double ReturnDiffereceBetweenTwoDatesInMonths(DateTime startDateTime, DateTime endDateTime)
{
double result = 0;
double days = 0;
DateTime currentDateTime = startDateTime;
while (endDateTime > currentDateTime.AddMonths(1))
{
result ++;
currentDateTime = currentDateTime.AddMonths(1);
}
if (endDateTime > currentDateTime)
{
days = endDateTime.Subtract(currentDateTime).TotalDays;
}
return result + days/endDateTime.GetMonthDays;
}
简单快速的解决方案,计算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;
}
这个简单的静态函数计算两个Datetimes之间的月份分数。
1.1. 到31.1。= 1.0 1.4. 到15.4。= 0.5 16.4. 到30.4。= 0.5 1.3. 到1.4。= 1 + 1/30
该函数假设第一个日期比第二个日期小。要处理负时间间隔,可以通过在开始时引入符号和变量交换来轻松地修改函数。
public static double GetDeltaMonths(DateTime t0, DateTime t1)
{
DateTime t = t0;
double months = 0;
while(t<=t1)
{
int daysInMonth = DateTime.DaysInMonth(t.Year, t.Month);
DateTime endOfMonth = new DateTime(t.Year, t.Month, daysInMonth);
int cutDay = endOfMonth <= t1 ? daysInMonth : t1.Day;
months += (cutDay - t.Day + 1) / (double) daysInMonth;
t = new DateTime(t.Year, t.Month, 1).AddMonths(1);
}
return Math.Round(months,2);
}
如果您想要完整月份的确切数目,总是正的(2000-01-15,2000-02-14返回0),则考虑完整月份是当您到达下个月的同一天时(类似于年龄计算)
public static int GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
return monthDiff - 1;
}
else
{
return monthDiff;
}
}
编辑原因:旧代码在某些情况下不正确,如:
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
Test cases I used to test the function:
var tests = new[]
{
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
};
在这个问题上没有很多明确的答案,因为你总是在假设事情。
这个解决方案在两个日期之间进行计算,假设您想保存一个月中的某一天进行比较,(这意味着在计算中考虑了这个月中的某一天)
例如,如果你的日期是2012年1月30日,2012年2月29日就不是一个月,但2013年3月1日就不是一个月。
它经过了相当彻底的测试,可能稍后我们会在使用时清理它,但这里:
private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
{
int intReturn = 0;
bool sameMonth = false;
if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
intReturn--;
int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days
int daysinMonth = 0; //used to caputre how many days are in the month
while (dtOther.Date > dtThis.Date) //while Other date is still under the other
{
dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month
if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
{
if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month
dtThis.AddDays(daysinMonth - dtThis.Day);
else
dtThis.AddDays(dayOfMonth - dtThis.Day);
}
if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
{
if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
intReturn++;
sameMonth = true; //sets this to cancel out of the normal counting of month
}
if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month)
intReturn++;
}
return intReturn; //return month
}