如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
当前回答
这个简单的静态函数计算两个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);
}
其他回答
我当时在做一个项目,只需要几年和几个月。
/// <summary>
/// Get the total months between two date. This will count whole months and not care about the day.
/// </summary>
/// <param name="firstDate">First date.</param>
/// <param name="lastDate">Last date.</param>
/// <returns>Number of month apart.</returns>
private static int GetTotalMonths(DateOnly firstDate, DateOnly lastDate)
{
int yearsApart = lastDate.Year - firstDate.Year;
int monthsApart = lastDate.Month - firstDate.Month;
return (yearsApart * 12) + monthsApart;
}
private static int GetTotalMonths(DateTime firstDate, DateTime lastDate)
{
return GetTotalMonths(DateOnly.FromDateTime(firstDate), DateOnly.FromDateTime(lastDate));
}
使用野田时间:
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
(例子)
我写了一个函数来完成这个,因为其他的方法都不适合我。
public string getEndDate (DateTime startDate,decimal monthCount)
{
int y = startDate.Year;
int m = startDate.Month;
for (decimal i = monthCount; i > 1; i--)
{
m++;
if (m == 12)
{ y++;
m = 1;
}
}
return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString());
}
这是我自己的库,将返回两个日期之间的月差。
public static int MonthDiff(DateTime d1, DateTime d2)
{
int retVal = 0;
// Calculate the number of years represented and multiply by 12
// Substract the month number from the total
// Substract the difference of the second month and 12 from the total
retVal = (d1.Year - d2.Year) * 12;
retVal = retVal - d1.Month;
retVal = retVal - (12 - d2.Month);
return retVal;
}
似乎DateTimeSpan解决方案使许多人满意。我不知道。让我们考虑一下:
BeginDate = 1972/2/29销售= 1972/4/28。
基于DateTimeSpan的答案是:
1年(s), 2个月(s)和0天(s)
我实现了一个方法,在此基础上,答案是:
1年、1个月及28天
显然没有两个月的时间。我想说的是,因为我们在开始日期的月末,剩下的实际上是整个3月加上结束日期(4月)的月份所经过的天数,所以1个月零28天。
如果你读到这里,你有兴趣,我把方法贴在下面。我在评论中解释了我所做的假设,因为有多少个月,月份的概念是一个不断变化的目标。多次测试,看看答案是否有意义。我通常选择相邻年份的考试日期,一旦我确认了答案,我就会前后移动一两天。到目前为止,它看起来不错,我相信你会发现一些bug:D。代码可能看起来有点粗糙,但我希望它足够清楚:
static void Main(string[] args) {
DateTime EndDate = new DateTime(1973, 4, 28);
DateTime BeginDate = new DateTime(1972, 2, 29);
int years, months, days;
GetYearsMonthsDays(EndDate, BeginDate, out years, out months, out days);
Console.WriteLine($"{years} year(s), {months} month(s) and {days} day(s)");
}
/// <summary>
/// Calculates how many years, months and days are between two dates.
/// </summary>
/// <remarks>
/// The fundamental idea here is that most of the time all of us agree
/// that a month has passed today since the same day of the previous month.
/// A particular case is when both days are the last days of their respective months
/// when again we can say one month has passed.
/// In the following cases the idea of a month is a moving target.
/// - When only the beginning date is the last day of the month then we're left just with
/// a number of days from the next month equal to the day of the month that end date represent
/// - When only the end date is the last day of its respective month we clearly have a
/// whole month plus a few days after the the day of the beginning date until the end of its
/// respective months
/// In all the other cases we'll check
/// - beginingDay > endDay -> less then a month just daysToEndofBeginingMonth + dayofTheEndMonth
/// - beginingDay < endDay -> full month + (endDay - beginingDay)
/// - beginingDay == endDay -> one full month 0 days
///
/// </remarks>
///
private static void GetYearsMonthsDays(DateTime EndDate, DateTime BeginDate, out int years, out int months, out int days ) {
var beginMonthDays = DateTime.DaysInMonth(BeginDate.Year, BeginDate.Month);
var endMonthDays = DateTime.DaysInMonth(EndDate.Year, EndDate.Month);
// get the full years
years = EndDate.Year - BeginDate.Year - 1;
// how many full months in the first year
var firstYearMonths = 12 - BeginDate.Month;
// how many full months in the last year
var endYearMonths = EndDate.Month - 1;
// full months
months = firstYearMonths + endYearMonths;
days = 0;
// Particular end of month cases
if(beginMonthDays == BeginDate.Day && endMonthDays == EndDate.Day) {
months++;
}
else if(beginMonthDays == BeginDate.Day) {
days += EndDate.Day;
}
else if(endMonthDays == EndDate.Day) {
days += beginMonthDays - BeginDate.Day;
}
// For all the other cases
else if(EndDate.Day > BeginDate.Day) {
months++;
days += EndDate.Day - BeginDate.Day;
}
else if(EndDate.Day < BeginDate.Day) {
days += beginMonthDays - BeginDate.Day;
days += EndDate.Day;
}
else {
months++;
}
if(months >= 12) {
years++;
months = months - 12;
}
}