如何在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 partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
label3.Text = new DateDifference(Convert.ToDateTime("2018-09-13"), Convert.ToDateTime("2018-11-15")).ToString();
label2.Text = new DateDifference(Convert.ToDateTime("2018-10-12"), Convert.ToDateTime("2018-11-15")).ToString();
DateDifference oDateDifference = new DateDifference(Convert.ToDateTime("2018-11-12"));
label1.Text = oDateDifference.ToString();
}
}
public class DateDifference
{
public DateTime start { get; set; }
public DateTime currentDAte { get; set; }
public DateTime origstart { get; set; }
public DateTime origCurrentDAte { get; set; }
int days { get; set; }
int months { get; set; }
int years { get; set; }
public DateDifference(DateTime postedDate, DateTime currentDAte)
{
this.start = this.removeTime(postedDate);
this.currentDAte = this.removeTime(currentDAte);
this.origstart = postedDate;
this.origCurrentDAte = currentDAte;
}
public DateDifference(DateTime postedDate)
{
DateTime currentDate_ = DateTime.Now;
this.start = this.removeTime(postedDate);
this.currentDAte = this.removeTime(currentDate_);
this.origstart = postedDate;
this.origCurrentDAte = currentDate_;
if (start > this.currentDAte)
{
throw new Exception("Current date is greater than date posted");
}
this.compute();
}
void compute()
{
while (this.start.Year <= this.currentDAte.Year)
{
if (this.start.Year <= this.currentDAte.Year && (this.start.AddMonths(1) <= this.currentDAte))
{
++this.months;
this.start = this.start.AddMonths(1);
}
if ((this.start.Year == this.currentDAte.Year) && (this.start >= this.currentDAte.AddMonths(-1) && this.start <= this.currentDAte))
{
break;
}
}
while (this.start.DayOfYear < this.currentDAte.DayOfYear)
{
++this.days;
this.start = start.AddDays(1);
}
if (this.months > 11)
{
while (this.months > 11)
{
++this.years;
this.months = months - 12;
}
}
}
public override string ToString()
{
if (this.start > this.currentDAte)
{
throw new Exception("Current date is greater than date posted");
}
String ret = this.ComposeTostring();
this.reset();
return ret;
}
private String ComposeTostring()
{
this.compute();
if (this.years > 0)
{
if (this.months > 0)
{
if (this.days > 0)
{
return String.Format("{0} year{1}, {2} month{3} && {4} Day{5} ago", this.years, plural(this.years), this.months, plural(this.months), this.days, plural(this.days));
}
return String.Format("{0} year{1}, {2} month{3} ago", this.years, plural(this.years), this.months, plural(this.months));
}
else
{
if (this.days > 0)
{
return String.Format("{0} year{1},{2} day{3} ago", this.years, plural(this.years), this.days, plural(this.days));
}
return String.Format("{0} year{1} ago", this.years, plural(this.years));
}
}
if (this.months > 0)
{
if (this.days > 0)
{
return String.Format("{0} month{1}, {2} day{3} ago", this.months, plural(this.months), this.days, plural(this.days));
}
else
{
return String.Format("{0} month{1} ago", this.months, plural(this.months));
}
}
if ((this.origCurrentDAte - this.origstart).Days > 0)
{
int daysDiff = (this.origCurrentDAte - this.origstart).Days;
this.origstart = this.origstart.AddDays(daysDiff);
int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
return String.Format("{0} day{1}, {2} hour{3} ago", daysDiff, plural(daysDiff), HoursDiff, plural(HoursDiff));
}
else if ((this.origCurrentDAte - this.origstart).Hours > 0)
{
int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
this.origstart = this.origstart.AddHours(HoursDiff);
int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
return String.Format("{0} hour{1}, {2} minute{3} ago", HoursDiff, plural(HoursDiff), MinDiff, plural(MinDiff));
}
else if ((this.origCurrentDAte - this.origstart).Minutes > 0)
{
int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
this.origstart = this.origstart.AddMinutes(MinDiff);
int SecDiff = (this.origCurrentDAte - this.origstart).Seconds;
return String.Format("{0} minute{1}, {2} second{3} ago", MinDiff, plural(MinDiff), SecDiff, plural(SecDiff));
}
else if ((this.origCurrentDAte - this.origstart).Seconds > 0)
{
int sec = (this.origCurrentDAte - this.origstart).Seconds;
return String.Format("{0} second{1}", sec, plural(sec));
}
return "";
}
String plural(int val)
{
return (val > 1 ? "s" : String.Empty);
}
DateTime removeTime(DateTime dtime)
{
dtime = dtime.AddHours(-dtime.Hour);
dtime = dtime.AddMinutes(-dtime.Minute);
dtime = dtime.AddSeconds(-dtime.Second);
return dtime;
}
public void reset()
{
this.days = 0;
this.months = 0;
this.years = 0;
this.start = DateTime.MinValue;
this.currentDAte = DateTime.MinValue;
this.origstart = DateTime.MinValue;
this.origCurrentDAte = DateTime.MinValue;
}
}
其他回答
简单的修复。工作的100%
var exactmonth = (date1.Year - date2.Year) * 12 + date1.Month -
date2.Month + (date1.Day >= date2.Day ? 0 : -1);
Console.WriteLine(exactmonth);
我当时在做一个项目,只需要几年和几个月。
/// <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));
}
基于上面出色的DateTimeSpan工作,我将代码规范化了一些;这似乎很有效:
public class DateTimeSpan
{
private DateTimeSpan() { }
private DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
{
Years = years;
Months = months;
Days = days;
Hours = hours;
Minutes = minutes;
Seconds = seconds;
Milliseconds = milliseconds;
}
public int Years { get; private set; } = 0;
public int Months { get; private set; } = 0;
public int Days { get; private set; } = 0;
public int Hours { get; private set; } = 0;
public int Minutes { get; private set; } = 0;
public int Seconds { get; private set; } = 0;
public int Milliseconds { get; private set; } = 0;
public static DateTimeSpan CompareDates(DateTime StartDate, DateTime EndDate)
{
if (StartDate.Equals(EndDate)) return new DateTimeSpan();
DateTimeSpan R = new DateTimeSpan();
bool Later;
if (Later = StartDate > EndDate)
{
DateTime D = StartDate;
StartDate = EndDate;
EndDate = D;
}
// Calculate Date Stuff
for (DateTime D = StartDate.AddYears(1); D < EndDate; D = D.AddYears(1), R.Years++) ;
if (R.Years > 0) StartDate = StartDate.AddYears(R.Years);
for (DateTime D = StartDate.AddMonths(1); D < EndDate; D = D.AddMonths(1), R.Months++) ;
if (R.Months > 0) StartDate = StartDate.AddMonths(R.Months);
for (DateTime D = StartDate.AddDays(1); D < EndDate; D = D.AddDays(1), R.Days++) ;
if (R.Days > 0) StartDate = StartDate.AddDays(R.Days);
// Calculate Time Stuff
TimeSpan T1 = EndDate - StartDate;
R.Hours = T1.Hours;
R.Minutes = T1.Minutes;
R.Seconds = T1.Seconds;
R.Milliseconds = T1.Milliseconds;
// Return answer. Negate values if the Start Date was later than the End Date
if (Later)
return new DateTimeSpan(-R.Years, -R.Months, -R.Days, -R.Hours, -R.Minutes, -R.Seconds, -R.Milliseconds);
return R;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
label3.Text = new DateDifference(Convert.ToDateTime("2018-09-13"), Convert.ToDateTime("2018-11-15")).ToString();
label2.Text = new DateDifference(Convert.ToDateTime("2018-10-12"), Convert.ToDateTime("2018-11-15")).ToString();
DateDifference oDateDifference = new DateDifference(Convert.ToDateTime("2018-11-12"));
label1.Text = oDateDifference.ToString();
}
}
public class DateDifference
{
public DateTime start { get; set; }
public DateTime currentDAte { get; set; }
public DateTime origstart { get; set; }
public DateTime origCurrentDAte { get; set; }
int days { get; set; }
int months { get; set; }
int years { get; set; }
public DateDifference(DateTime postedDate, DateTime currentDAte)
{
this.start = this.removeTime(postedDate);
this.currentDAte = this.removeTime(currentDAte);
this.origstart = postedDate;
this.origCurrentDAte = currentDAte;
}
public DateDifference(DateTime postedDate)
{
DateTime currentDate_ = DateTime.Now;
this.start = this.removeTime(postedDate);
this.currentDAte = this.removeTime(currentDate_);
this.origstart = postedDate;
this.origCurrentDAte = currentDate_;
if (start > this.currentDAte)
{
throw new Exception("Current date is greater than date posted");
}
this.compute();
}
void compute()
{
while (this.start.Year <= this.currentDAte.Year)
{
if (this.start.Year <= this.currentDAte.Year && (this.start.AddMonths(1) <= this.currentDAte))
{
++this.months;
this.start = this.start.AddMonths(1);
}
if ((this.start.Year == this.currentDAte.Year) && (this.start >= this.currentDAte.AddMonths(-1) && this.start <= this.currentDAte))
{
break;
}
}
while (this.start.DayOfYear < this.currentDAte.DayOfYear)
{
++this.days;
this.start = start.AddDays(1);
}
if (this.months > 11)
{
while (this.months > 11)
{
++this.years;
this.months = months - 12;
}
}
}
public override string ToString()
{
if (this.start > this.currentDAte)
{
throw new Exception("Current date is greater than date posted");
}
String ret = this.ComposeTostring();
this.reset();
return ret;
}
private String ComposeTostring()
{
this.compute();
if (this.years > 0)
{
if (this.months > 0)
{
if (this.days > 0)
{
return String.Format("{0} year{1}, {2} month{3} && {4} Day{5} ago", this.years, plural(this.years), this.months, plural(this.months), this.days, plural(this.days));
}
return String.Format("{0} year{1}, {2} month{3} ago", this.years, plural(this.years), this.months, plural(this.months));
}
else
{
if (this.days > 0)
{
return String.Format("{0} year{1},{2} day{3} ago", this.years, plural(this.years), this.days, plural(this.days));
}
return String.Format("{0} year{1} ago", this.years, plural(this.years));
}
}
if (this.months > 0)
{
if (this.days > 0)
{
return String.Format("{0} month{1}, {2} day{3} ago", this.months, plural(this.months), this.days, plural(this.days));
}
else
{
return String.Format("{0} month{1} ago", this.months, plural(this.months));
}
}
if ((this.origCurrentDAte - this.origstart).Days > 0)
{
int daysDiff = (this.origCurrentDAte - this.origstart).Days;
this.origstart = this.origstart.AddDays(daysDiff);
int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
return String.Format("{0} day{1}, {2} hour{3} ago", daysDiff, plural(daysDiff), HoursDiff, plural(HoursDiff));
}
else if ((this.origCurrentDAte - this.origstart).Hours > 0)
{
int HoursDiff = (this.origCurrentDAte - this.origstart).Hours;
this.origstart = this.origstart.AddHours(HoursDiff);
int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
return String.Format("{0} hour{1}, {2} minute{3} ago", HoursDiff, plural(HoursDiff), MinDiff, plural(MinDiff));
}
else if ((this.origCurrentDAte - this.origstart).Minutes > 0)
{
int MinDiff = (this.origCurrentDAte - this.origstart).Minutes;
this.origstart = this.origstart.AddMinutes(MinDiff);
int SecDiff = (this.origCurrentDAte - this.origstart).Seconds;
return String.Format("{0} minute{1}, {2} second{3} ago", MinDiff, plural(MinDiff), SecDiff, plural(SecDiff));
}
else if ((this.origCurrentDAte - this.origstart).Seconds > 0)
{
int sec = (this.origCurrentDAte - this.origstart).Seconds;
return String.Format("{0} second{1}", sec, plural(sec));
}
return "";
}
String plural(int val)
{
return (val > 1 ? "s" : String.Empty);
}
DateTime removeTime(DateTime dtime)
{
dtime = dtime.AddHours(-dtime.Hour);
dtime = dtime.AddMinutes(-dtime.Minute);
dtime = dtime.AddSeconds(-dtime.Second);
return dtime;
}
public void reset()
{
this.days = 0;
this.months = 0;
this.years = 0;
this.start = DateTime.MinValue;
this.currentDAte = DateTime.MinValue;
this.origstart = DateTime.MinValue;
this.origCurrentDAte = DateTime.MinValue;
}
}
你可以有一个这样的函数。
例如,从2012/12/27到2012/12/29变成3天。同样,从2012/12/15到2013/01/15变成了2个月,因为到2013/01/14是1个月。从15号开始是第二个月。
如果您不想在计算中包括这两天,则可以删除第二个if条件中的“=”。即从2012/12/15到2013/01/15为1个月。
public int GetMonths(DateTime startDate, DateTime endDate)
{
if (startDate > endDate)
{
throw new Exception("Start Date is greater than the End Date");
}
int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month);
if (endDate.Day >= startDate.Day)
{
months++;
}
return months;
}