如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
当前回答
使用野田时间:
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
(例子)
其他回答
下面是一个使用VB的更简洁的解决方案。只适用于年、月、日的净日期。你也可以在c#中加载DateDiff库。
Date1必须<= date2
VB。网
Dim date1 = Now.AddDays(-2000)
Dim date2 = Now
Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0)
Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0)
Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day))
C#
DateTime date1 = Now.AddDays(-2000);
DateTime date2 = Now;
int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0;
int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0;
int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day);
Public Class ClassDateOperation
Private prop_DifferenceInDay As Integer
Private prop_DifferenceInMonth As Integer
Private prop_DifferenceInYear As Integer
Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation
Dim differenceInDay As Integer
Dim differenceInMonth As Integer
Dim differenceInYear As Integer
Dim myDate As Date
DateEnd = DateEnd.AddDays(1)
differenceInYear = DateEnd.Year - DateStart.Year
If DateStart.Month <= DateEnd.Month Then
differenceInMonth = DateEnd.Month - DateStart.Month
Else
differenceInYear -= 1
differenceInMonth = (12 - DateStart.Month) + DateEnd.Month
End If
If DateStart.Day <= DateEnd.Day Then
differenceInDay = DateEnd.Day - DateStart.Day
Else
myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1)
If differenceInMonth <> 0 Then
differenceInMonth -= 1
Else
differenceInMonth = 11
differenceInYear -= 1
End If
differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day
End If
prop_DifferenceInDay = differenceInDay
prop_DifferenceInMonth = differenceInMonth
prop_DifferenceInYear = differenceInYear
Return Me
End Function
Public ReadOnly Property DifferenceInDay() As Integer
Get
Return prop_DifferenceInDay
End Get
End Property
Public ReadOnly Property DifferenceInMonth As Integer
Get
Return prop_DifferenceInMonth
End Get
End Property
Public ReadOnly Property DifferenceInYear As Integer
Get
Return prop_DifferenceInYear
End Get
End Property
End Class
我在VB中检查了这个方法的用法。NET通过MSDN,它似乎有很多用途。c#中没有这样的内置方法。(即使这不是一个好主意)你可以在c#中调用VB。
将Microsoft.VisualBasic.dll添加到 你的项目作为参考 使用 Microsoft.VisualBasic.DateAndTime.DateDiff 在代码中
在这个问题上没有很多明确的答案,因为你总是在假设事情。
这个解决方案在两个日期之间进行计算,假设您想保存一个月中的某一天进行比较,(这意味着在计算中考虑了这个月中的某一天)
例如,如果你的日期是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
}
似乎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;
}
}