如何在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;
}
}
其他回答
这是我自己的库,将返回两个日期之间的月差。
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的综合解决方案,它与TimeSpan类似,不同之处是它除了时间组件之外还包括所有的日期组件。
用法:
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 = DateTimeSpan.CompareDates(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);
}
输出:
年:1 第五个月: 天:27 时间:1 分钟:36 50秒: 毫秒:0
为了方便起见,我将逻辑集中到DateTimeSpan结构体中,但是您可以将方法CompareDates移动到任何您认为合适的地方。还要注意,哪个日期在另一个日期之前并不重要。
public struct DateTimeSpan
{
public int Years { get; }
public int Months { get; }
public int Days { get; }
public int Hours { get; }
public int Minutes { get; }
public int Seconds { get; }
public int Milliseconds { get; }
public 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;
}
enum Phase { Years, Months, Days, Done }
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();
int officialDay = current.Day;
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);
if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
current = current.AddDays(officialDay - current.Day);
}
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;
}
}
我只是需要一些简单的东西来满足例如,只输入月份/年的就业日期,所以希望工作的年份和月份不同。这就是我所使用的,只是为了实用
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小提琴
在这个问题上没有很多明确的答案,因为你总是在假设事情。
这个解决方案在两个日期之间进行计算,假设您想保存一个月中的某一天进行比较,(这意味着在计算中考虑了这个月中的某一天)
例如,如果你的日期是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
}
你可以使用野田时间https://nodatime.org/
LocalDate start = new LocalDate(2010, 1, 5);
LocalDate end = new LocalDate(2012, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months);