如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
如何在c#中计算两个日期之间的月差?
c#中是否有相当于VB的DateDiff()方法。我需要找出相隔数年的两个日期之间的月差。文档说我可以像这样使用TimeSpan:
TimeSpan ts = date1 - date2;
但这里的数据是以天为单位的。我不想把这个数字除以30,因为不是每个月都是30天,而且两个操作数的值相差很大,所以我担心除以30可能会得到错误的值。
有什么建议吗?
当前回答
我只是需要一些简单的东西来满足例如,只输入月份/年的就业日期,所以希望工作的年份和月份不同。这就是我所使用的,只是为了实用
public static YearsMonths YearMonthDiff(DateTime startDate, DateTime endDate) {
int monthDiff = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month) + 1;
int years = (int)Math.Floor((decimal) (monthDiff / 12));
int months = monthDiff % 12;
return new YearsMonths {
TotalMonths = monthDiff,
Years = years,
Months = months
};
}
net小提琴
其他回答
这是对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);
}
扩展的Kirks结构与ToString(格式)和持续时间(长ms)
public struct DateTimeSpan
{
private readonly int years;
private readonly int months;
private readonly int days;
private readonly int hours;
private readonly int minutes;
private readonly int seconds;
private readonly int milliseconds;
public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.milliseconds = 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; } }
enum Phase { Years, Months, Days, Done }
public string ToString(string format)
{
format = format.Replace("YYYY", Years.ToString());
format = format.Replace("MM", Months.ToString());
format = format.Replace("DD", Days.ToString());
format = format.Replace("hh", Hours.ToString());
format = format.Replace("mm", Minutes.ToString());
format = format.Replace("ss", Seconds.ToString());
format = format.Replace("ms", Milliseconds.ToString());
return format;
}
public static DateTimeSpan Duration(long ms)
{
DateTime dt = new DateTime();
return CompareDates(dt, dt.AddMilliseconds(ms));
}
public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
{
if (date2 < date1)
{
var sub = date1;
date1 = date2;
date2 = sub;
}
DateTime current = date1;
int years = 0;
int months = 0;
int days = 0;
Phase phase = Phase.Years;
DateTimeSpan span = new DateTimeSpan();
while (phase != Phase.Done)
{
switch (phase)
{
case Phase.Years:
if (current.AddYears(years + 1) > date2)
{
phase = Phase.Months;
current = current.AddYears(years);
}
else
{
years++;
}
break;
case Phase.Months:
if (current.AddMonths(months + 1) > date2)
{
phase = Phase.Days;
current = current.AddMonths(months);
}
else
{
months++;
}
break;
case Phase.Days:
if (current.AddDays(days + 1) > date2)
{
current = current.AddDays(days);
var timespan = date2 - current;
span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
phase = Phase.Done;
}
else
{
days++;
}
break;
}
}
return span;
}
}
我的问题用这个方法解决了:
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.
//
}
int nMonths = 0;
if (FDate.ToDateTime().Year == TDate.ToDateTime().Year)
nMonths = TDate.ToDateTime().Month - FDate.ToDateTime().Month;
else
nMonths = (12 - FDate.Month) + TDate.Month;
LINQ的解决方案,
DateTime ToDate = DateTime.Today;
DateTime FromDate = ToDate.Date.AddYears(-1).AddDays(1);
int monthCount = Enumerable.Range(0, 1 + ToDate.Subtract(FromDate).Days)
.Select(x => FromDate.AddDays(x))
.ToList<DateTime>()
.GroupBy(z => new { z.Year, z.Month })
.Count();