我如何在JavaScript中计算出两个Date()对象的差异,而只返回差异中的月份数?
任何帮助都是最好的:)
我如何在JavaScript中计算出两个Date()对象的差异,而只返回差异中的月份数?
任何帮助都是最好的:)
当前回答
getMonthDiff(d1, d2) {
var year1 = dt1.getFullYear();
var year2 = dt2.getFullYear();
var month1 = dt1.getMonth();
var month2 = dt2.getMonth();
var day1 = dt1.getDate();
var day2 = dt2.getDate();
var months = month2 - month1;
var years = year2 -year1
days = day2 - day1;
if (days < 0) {
months -= 1;
}
if (months < 0) {
months += 12;
}
return months + years*!2;
}
其他回答
有两种方法,数学的和快速的,但受制于日历的变幻莫测,或者迭代的和缓慢的,但处理所有奇怪的(或者至少委托处理它们到一个经过良好测试的库)。
If you iterate through the calendar, incrementing the start date by one month & seeing if we pass the end date. This delegates anomaly-handling to the built-in Date() classes, but could be slow IF you're doing this for a large number of dates. James' answer takes this approach. As much as I dislike the idea, I think this is the "safest" approach, and if you're only doing one calculation, the performance difference really is negligible. We tend to try to over-optimize tasks which will only be performed once.
现在,如果您在数据集中计算这个函数,您可能不希望在每一行上运行该函数(或者上帝禁止,每条记录多次)。在这种情况下,您几乎可以使用这里的任何其他答案,除了接受的答案,这是错误的(new Date()和new Date()之间的差异是-1)?
下面是我尝试的一种数学而快速的方法,它解释了不同的月份长度和闰年。你真的应该只使用这样的函数,如果你将应用它到一个数据集(做这个计算一遍又一遍)。如果只需要执行一次,可以使用上面James的迭代方法,因为您正在将所有(许多)异常的处理委托给Date()对象。
function diffInMonths(from, to){
var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
if (to < newFrom && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
months--;
}
}
return months;
}
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
d2month = d2.getMonth();
d2year = d2.getFullYear();
d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24)));
d1new = new Date(d2year, d2month, 1,0,0,0,0);
d1new.setDate(d1new.getDate()-1);
d1maxday = d1new.getDate();
months += diffdate / d1maxday;
}
else
{
if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
{
months += 1;
}
diffdate = d2day - d1day + 1;
d2month = d2.getMonth();
d2year = d2.getFullYear();
d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
d2new.setDate(d2new.getDate()-1);
d2maxday = d2new.getDate();
months += diffdate / d2maxday;
}
return months;
}
你也可以考虑这个解决方案,这个函数返回整数或数字形式的月差
将开始日期作为第一个或最后一个参数传递是容错的。这意味着,函数仍然会返回相同的值。
const diffInMonths = (end, start) => { var timeDiff = Math.abs(end.getTime() - start.getTime()); 返回数学。round(timeDiff / (2e3 * 3600 * 365.25)); } const result = diffInMonths(new Date(2015, 3,28), new Date(2010, 1,25)); //显示月差值为整数/数字 console.log(结果);
我知道这真的很晚了,但还是把它贴出来,以防它能帮助到其他人。下面是我想出的一个函数,它似乎很好地计算了两个日期之间的月份差异。不可否认,这个方法比克劳德的方法要粗俗得多,但通过遍历日期对象提供了更准确的结果。它是在AS3中,但你应该能够放弃强类型,你会有JS。请随意让大家看起来更漂亮!
function countMonths ( startDate:Date, endDate:Date ):int
{
var stepDate:Date = new Date;
stepDate.time = startDate.time;
var monthCount:int;
while( stepDate.time <= endDate.time ) {
stepDate.month += 1;
monthCount += 1;
}
if ( stepDate != endDate ) {
monthCount -= 1;
}
return monthCount;
}
下面的代码还将部分月份中的nr天考虑在内,从而返回两个日期之间的完整月份。
var monthDiff = function(d1, d2) {
if( d2 < d1 ) {
var dTmp = d2;
d2 = d1;
d1 = dTmp;
}
var months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
if( d1.getDate() <= d2.getDate() ) months += 1;
return months;
}
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0
monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0