如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
当前回答
这是对Kirk Woll的回答的回应。我还没有足够的声望点来回复评论……
我喜欢Kirk的解决方案,并打算无耻地窃取它并在我的代码中使用它,但当我仔细查看它时,我意识到它太复杂了。不必要的切换和循环,以及使用毫无意义的公共构造函数。
以下是我的改写:
public class DateTimeSpan {
private DateTime _date1;
private DateTime _date2;
private int _years;
private int _months;
private int _days;
private int _hours;
private int _minutes;
private int _seconds;
private int _milliseconds;
public int Years { get { return _years; } }
public int Months { get { return _months; } }
public int Days { get { return _days; } }
public int Hours { get { return _hours; } }
public int Minutes { get { return _minutes; } }
public int Seconds { get { return _seconds; } }
public int Milliseconds { get { return _milliseconds; } }
public DateTimeSpan(DateTime date1, DateTime date2) {
_date1 = (date1 > date2) ? date1 : date2;
_date2 = (date2 < date1) ? date2 : date1;
_years = _date1.Year - _date2.Year;
_months = (_years * 12) + _date1.Month - _date2.Month;
TimeSpan t = (_date2 - _date1);
_days = t.Days;
_hours = t.Hours;
_minutes = t.Minutes;
_seconds = t.Seconds;
_milliseconds = t.Milliseconds;
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
return new DateTimeSpan(date1, date2);
}
}
用法1,基本相同:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
var dateSpan = new DateTimeSpan(compareTo, now);
Console.WriteLine("Years: " + dateSpan.Years);
Console.WriteLine("Months: " + dateSpan.Months);
Console.WriteLine("Days: " + dateSpan.Days);
Console.WriteLine("Hours: " + dateSpan.Hours);
Console.WriteLine("Minutes: " + dateSpan.Minutes);
Console.WriteLine("Seconds: " + dateSpan.Seconds);
Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}
Usage2类似:
void Main()
{
DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years);
Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months);
Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days);
Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours);
Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes);
Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds);
Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds);
}
其他回答
如果你只关心月份和年份,想要触及两个日期(例如你想要从JAN/2021到AGO/2022),你可以使用这个:
int numberOfMonths= (Year2 > Year1 ? ( Year2 - Year1 - 1) * 12 + (12 - Month1) + Month2 + 1 : Month2 - Month1 + 1);
例子:
Year1/Month1: 2021/10
Year2/Month2: 2022/08
numberOfMonths = 11;
或者同年:
Year1/Month1: 2021/10
Year2/Month2: 2021/12
numberOfMonths = 3;
如果你只想触碰其中一个,就去掉两个+ 1。
疯狂的方法,计算所有的日子,超级精确
Helper类:
public class DaysInMonth
{
public int Days { get; set; }
public int Month { get; set; }
public int Year { get; set; }
public bool Full { get; set; }
}
功能:
public static List<DaysInMonth> MonthsDelta(DateTime start, DateTime end)
{
var dates = Enumerable.Range(0, 1 + end.Subtract(start).Days)
.Select(offset => start.AddDays(offset))
.ToArray();
DateTime? prev = null;
int days = 0;
List < DaysInMonth > list = new List<DaysInMonth>();
foreach (DateTime date in dates)
{
if (prev != null)
{
if(date.Month!=prev.GetValueOrDefault().Month)
{
DaysInMonth daysInMonth = new DaysInMonth();
daysInMonth.Days = days;
daysInMonth.Month = prev.GetValueOrDefault().Month;
daysInMonth.Year = prev.GetValueOrDefault().Year;
daysInMonth.Full = DateTime.DaysInMonth(daysInMonth.Year, daysInMonth.Month) == daysInMonth.Days;
list.Add(daysInMonth);
days = 0;
}
}
days++;
prev = date;
}
//------------------ add last
if (days > 0)
{
DaysInMonth daysInMonth = new DaysInMonth();
daysInMonth.Days = days;
daysInMonth.Month = prev.GetValueOrDefault().Month;
daysInMonth.Year = prev.GetValueOrDefault().Year;
daysInMonth.Full = DateTime.DaysInMonth(daysInMonth.Year, daysInMonth.Month) == daysInMonth.Days;
list.Add(daysInMonth);
}
return list;
}
我们是这样做的:
public static int MonthDiff(DateTime date1, DateTime date2)
{
if (date1.Month < date2.Month)
{
return (date2.Year - date1.Year) * 12 + date2.Month - date1.Month;
}
else
{
return (date2.Year - date1.Year - 1) * 12 + date2.Month - date1.Month + 12;
}
}
我在VB中检查了这个方法的用法。NET通过MSDN,它似乎有很多用途。c#中没有这样的内置方法。(即使这不是一个好主意)你可以在c#中调用VB。
将Microsoft.VisualBasic.dll添加到 你的项目作为参考 使用 Microsoft.VisualBasic.DateAndTime.DateDiff 在代码中
假设这个月的日期不相关(即2011.1.1和2010.12.31之间的差为1),date1 > date2为正值,date2 > date1为负值
((date1.Year - date2.Year) * 12) + date1.Month - date2.Month
或者,假设你想要两个日期之间的“平均月”的大致数字,下面的方法应该适用于所有日期,但日期差异非常大。
date1.Subtract(date2).Days / (365.25 / 12)
注意,如果您要使用后一种解决方案,那么您的单元测试应该声明应用程序设计使用的最宽日期范围,并相应地验证计算结果。
更新(感谢Gary)
如果使用“平均月份”方法,“每年平均天数”的更准确数字是365.2425。