如何使用 moment.js 计算 Javascript 中两个日期之间的 'Working days' 数?
How to calculate Number of 'Working days' between two dates in Javascript using moment.js?
如何使用 moment.js 计算 JavaScript 中两个日期之间的工作日数。我有一个计算这些天的工作公式,但该公式不满足所有条件:
这是我的代码:
var start= moment(data[x].start_date);
var end= moment(data[x].est_end_date);
var difference= end.diff(start, 'days');
var workingDays= Math.round((difference/7)*5);
//data[x] is for iterating over a loop
这里我每 7 天得到 5 天,因为星期六和星期日被视为非工作日,但如果从星期日或星期六开始计算天数,此公式将失败。
请任何人在这方面提供帮助,必须进行哪些必要的更改才能避免此问题。
只需将其分为 3 个部分.. 第一周、上周和中间的部分,如下所示:
function workday_count(start,end) {
var first = start.clone().endOf('week'); // end of first week
var last = end.clone().startOf('week'); // start of last week
var days = last.diff(first,'days') * 5 / 7; // this will always multiply of 7
var wfirst = first.day() - start.day(); // check first week
if(start.day() == 0) --wfirst; // -1 if start with sunday
var wlast = end.day() - last.day(); // check last week
if(end.day() == 6) --wlast; // -1 if end with saturday
return wfirst + Math.floor(days) + wlast; // get the total
} // ^ EDIT: if days count less than 7 so no decimal point
测试代码
var ftest = {date:'2015-02-0',start:1,end:7};
var ltest = {date:'2015-02-2',start:2,end:8};
var f = 'YYYY-MM-DD';
for(var z=ftest.start; z<=ftest.end; ++z) {
var start = moment(ftest.date + z);
for(var y=ltest.start; y<=ltest.end; ++y) {
var end = moment(ltest.date + y);
var wd = workday_count(start,end);
console.log('from: '+start.format(f),'to: '+end.format(f),'is '+wd+' workday(s)');
}
}
测试代码输出:
from: 2015-02-01 to: 2015-02-22 is 15 workday(s)
from: 2015-02-01 to: 2015-02-23 is 16 workday(s)
from: 2015-02-01 to: 2015-02-24 is 17 workday(s)
from: 2015-02-01 to: 2015-02-25 is 18 workday(s)
from: 2015-02-01 to: 2015-02-26 is 19 workday(s)
from: 2015-02-01 to: 2015-02-27 is 20 workday(s)
from: 2015-02-01 to: 2015-02-28 is 20 workday(s)
from: 2015-02-02 to: 2015-02-22 is 15 workday(s)
from: 2015-02-02 to: 2015-02-23 is 16 workday(s)
from: 2015-02-02 to: 2015-02-24 is 17 workday(s)
from: 2015-02-02 to: 2015-02-25 is 18 workday(s)
from: 2015-02-02 to: 2015-02-26 is 19 workday(s)
from: 2015-02-02 to: 2015-02-27 is 20 workday(s)
from: 2015-02-02 to: 2015-02-28 is 20 workday(s)
from: 2015-02-03 to: 2015-02-22 is 14 workday(s)
from: 2015-02-03 to: 2015-02-23 is 15 workday(s)
from: 2015-02-03 to: 2015-02-24 is 16 workday(s)
from: 2015-02-03 to: 2015-02-25 is 17 workday(s)
from: 2015-02-03 to: 2015-02-26 is 18 workday(s)
from: 2015-02-03 to: 2015-02-27 is 19 workday(s)
from: 2015-02-03 to: 2015-02-28 is 19 workday(s)
from: 2015-02-04 to: 2015-02-22 is 13 workday(s)
from: 2015-02-04 to: 2015-02-23 is 14 workday(s)
from: 2015-02-04 to: 2015-02-24 is 15 workday(s)
from: 2015-02-04 to: 2015-02-25 is 16 workday(s)
from: 2015-02-04 to: 2015-02-26 is 17 workday(s)
from: 2015-02-04 to: 2015-02-27 is 18 workday(s)
from: 2015-02-04 to: 2015-02-28 is 18 workday(s)
from: 2015-02-05 to: 2015-02-22 is 12 workday(s)
from: 2015-02-05 to: 2015-02-23 is 13 workday(s)
from: 2015-02-05 to: 2015-02-24 is 14 workday(s)
from: 2015-02-05 to: 2015-02-25 is 15 workday(s)
from: 2015-02-05 to: 2015-02-26 is 16 workday(s)
from: 2015-02-05 to: 2015-02-27 is 17 workday(s)
from: 2015-02-05 to: 2015-02-28 is 17 workday(s)
from: 2015-02-06 to: 2015-02-22 is 11 workday(s)
from: 2015-02-06 to: 2015-02-23 is 12 workday(s)
from: 2015-02-06 to: 2015-02-24 is 13 workday(s)
from: 2015-02-06 to: 2015-02-25 is 14 workday(s)
from: 2015-02-06 to: 2015-02-26 is 15 workday(s)
from: 2015-02-06 to: 2015-02-27 is 16 workday(s)
from: 2015-02-06 to: 2015-02-28 is 16 workday(s)
from: 2015-02-07 to: 2015-02-22 is 10 workday(s)
from: 2015-02-07 to: 2015-02-23 is 11 workday(s)
from: 2015-02-07 to: 2015-02-24 is 12 workday(s)
from: 2015-02-07 to: 2015-02-25 is 13 workday(s)
from: 2015-02-07 to: 2015-02-26 is 14 workday(s)
from: 2015-02-07 to: 2015-02-27 is 15 workday(s)
from: 2015-02-07 to: 2015-02-28 is 15 workday(s)
我发现 kokizzu 的回答在同一周内(例如太阳到坐着)不起作用,所以改为解决这个问题:
function calcBusinessDays(startDate, endDate) {
var day = moment(startDate);
var businessDays = 0;
while (day.isSameOrBefore(endDate,'day')) {
if (day.day()!=0 && day.day()!=6) businessDays++;
day.add(1,'d');
}
return businessDays;
}
我对 Kokizzu 的回答进行了改编,以解决夏令时问题。在巴西时区 (GMT -3) 中,17/10/2017 和 18/10/2017 之间的差异是 -2.71 而不是 2.
一周的开始时间是 15/10/2017 00:00 UTC 或 14/10/2017 21:00-03:00
周末是 22/10/2017 00:00 UTC 或 21/10/2017 22:00-02:00(夏令时)
因此,"first" 和 "last" 变量之间的天数差异不是 7 天,而是 6 天(或 8 天,具体取决于您所在的时区)。
修复的代码如下:
start = moment(start).utc().add(start.utcOffset(), 'm'); // Ignore timezones
end = moment(end).utc().add(end.utcOffset(), 'm'); // Ignore timezones
var first = start.clone().endOf('week'); // end of first week
var last = end.clone().startOf('week'); // start of last week
// Fixing Summer Time problems
firstCorrection = moment(first).utc().add(60, 'm').toDate(); //
var days = last.diff(firstCorrection,'days') * 5 / 7; // this will always multiply of 7
var wfirst = first.day() - start.day(); // check first week
if(start.day() == 0) --wfirst; // -1 if start with sunday
var wlast = end.day() - last.day(); // check last week
if(end.day() == 6) --wlast; // -1 if end with saturday
return wfirst + days + wlast; // get the total (subtract holidays if needed)
我使用一个简单的函数来完成它。也许不是最有效的,但它确实有效。它不需要 Moment.js。只是 Javascript.
function getNumWorkDays(startDate, endDate) {
var numWorkDays = 0;
var currentDate = new Date(startDate);
while (currentDate <= endDate) {
// Skips Sunday and Saturday
if (currentDate.getDay() !== 0 && currentDate.getDay() !== 6) {
numWorkDays++;
}
currentDate = currentDate.addDays(1);
}
return numWorkDays;
}
为了addDays
,我使用了以下函数:
Date.prototype.addDays = function (days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
};
你可以试试这个(没有循环):
function getBusinessDays(endDate, startDate) {
var lastDay = moment(endDate);
var firstDay = moment(startDate);
let calcBusinessDays = 1 + (lastDay.diff(firstDay, 'days') * 5 -
(firstDay.day() - lastDay.day()) * 2) / 7;
if (lastDay.day() == 6) calcBusinessDays--;//SAT
if (firstDay.day() == 0) calcBusinessDays--;//SUN
return calcBusinessDays;
}
Original Source
通过使用momentjs,可以这样:
private calculateWorkdays(startDate: Date, endDate: Date): number {
// + 1 cause diff returns the difference between two moments, in this case the day itself should be included.
const totalDays: number = moment(endDate).diff(moment(startDate), 'days') + 1;
const dayOfWeek = moment(startDate).isoWeekday();
let totalWorkdays = 0;
for (let i = dayOfWeek; i < totalDays + dayOfWeek; i++) {
if (i % 7 !== 6 && i % 7 !== 0) {
totalWorkdays++;
}
}
return totalWorkdays;
}
我一直在使用一个有用的库moment-business-days加上moment
NPM Link of Moment-business-days
之间的工作日示例
const diff = moment('05-15-2017', 'MM-DD-YYYY').businessDiff(moment('05-08-2017','MM-DD-YYYY'));
// diff = 5
工作日应存储在数据库的 table 中并通过 API 提供,无法计算工作日。各国的假期不同,即使在美国每个州也可能有不同的假期,每个公司可能有不同的工作日
如何使用 moment.js 计算 JavaScript 中两个日期之间的工作日数。我有一个计算这些天的工作公式,但该公式不满足所有条件:
这是我的代码:
var start= moment(data[x].start_date);
var end= moment(data[x].est_end_date);
var difference= end.diff(start, 'days');
var workingDays= Math.round((difference/7)*5);
//data[x] is for iterating over a loop
这里我每 7 天得到 5 天,因为星期六和星期日被视为非工作日,但如果从星期日或星期六开始计算天数,此公式将失败。
请任何人在这方面提供帮助,必须进行哪些必要的更改才能避免此问题。
只需将其分为 3 个部分.. 第一周、上周和中间的部分,如下所示:
function workday_count(start,end) {
var first = start.clone().endOf('week'); // end of first week
var last = end.clone().startOf('week'); // start of last week
var days = last.diff(first,'days') * 5 / 7; // this will always multiply of 7
var wfirst = first.day() - start.day(); // check first week
if(start.day() == 0) --wfirst; // -1 if start with sunday
var wlast = end.day() - last.day(); // check last week
if(end.day() == 6) --wlast; // -1 if end with saturday
return wfirst + Math.floor(days) + wlast; // get the total
} // ^ EDIT: if days count less than 7 so no decimal point
测试代码
var ftest = {date:'2015-02-0',start:1,end:7};
var ltest = {date:'2015-02-2',start:2,end:8};
var f = 'YYYY-MM-DD';
for(var z=ftest.start; z<=ftest.end; ++z) {
var start = moment(ftest.date + z);
for(var y=ltest.start; y<=ltest.end; ++y) {
var end = moment(ltest.date + y);
var wd = workday_count(start,end);
console.log('from: '+start.format(f),'to: '+end.format(f),'is '+wd+' workday(s)');
}
}
测试代码输出:
from: 2015-02-01 to: 2015-02-22 is 15 workday(s)
from: 2015-02-01 to: 2015-02-23 is 16 workday(s)
from: 2015-02-01 to: 2015-02-24 is 17 workday(s)
from: 2015-02-01 to: 2015-02-25 is 18 workday(s)
from: 2015-02-01 to: 2015-02-26 is 19 workday(s)
from: 2015-02-01 to: 2015-02-27 is 20 workday(s)
from: 2015-02-01 to: 2015-02-28 is 20 workday(s)
from: 2015-02-02 to: 2015-02-22 is 15 workday(s)
from: 2015-02-02 to: 2015-02-23 is 16 workday(s)
from: 2015-02-02 to: 2015-02-24 is 17 workday(s)
from: 2015-02-02 to: 2015-02-25 is 18 workday(s)
from: 2015-02-02 to: 2015-02-26 is 19 workday(s)
from: 2015-02-02 to: 2015-02-27 is 20 workday(s)
from: 2015-02-02 to: 2015-02-28 is 20 workday(s)
from: 2015-02-03 to: 2015-02-22 is 14 workday(s)
from: 2015-02-03 to: 2015-02-23 is 15 workday(s)
from: 2015-02-03 to: 2015-02-24 is 16 workday(s)
from: 2015-02-03 to: 2015-02-25 is 17 workday(s)
from: 2015-02-03 to: 2015-02-26 is 18 workday(s)
from: 2015-02-03 to: 2015-02-27 is 19 workday(s)
from: 2015-02-03 to: 2015-02-28 is 19 workday(s)
from: 2015-02-04 to: 2015-02-22 is 13 workday(s)
from: 2015-02-04 to: 2015-02-23 is 14 workday(s)
from: 2015-02-04 to: 2015-02-24 is 15 workday(s)
from: 2015-02-04 to: 2015-02-25 is 16 workday(s)
from: 2015-02-04 to: 2015-02-26 is 17 workday(s)
from: 2015-02-04 to: 2015-02-27 is 18 workday(s)
from: 2015-02-04 to: 2015-02-28 is 18 workday(s)
from: 2015-02-05 to: 2015-02-22 is 12 workday(s)
from: 2015-02-05 to: 2015-02-23 is 13 workday(s)
from: 2015-02-05 to: 2015-02-24 is 14 workday(s)
from: 2015-02-05 to: 2015-02-25 is 15 workday(s)
from: 2015-02-05 to: 2015-02-26 is 16 workday(s)
from: 2015-02-05 to: 2015-02-27 is 17 workday(s)
from: 2015-02-05 to: 2015-02-28 is 17 workday(s)
from: 2015-02-06 to: 2015-02-22 is 11 workday(s)
from: 2015-02-06 to: 2015-02-23 is 12 workday(s)
from: 2015-02-06 to: 2015-02-24 is 13 workday(s)
from: 2015-02-06 to: 2015-02-25 is 14 workday(s)
from: 2015-02-06 to: 2015-02-26 is 15 workday(s)
from: 2015-02-06 to: 2015-02-27 is 16 workday(s)
from: 2015-02-06 to: 2015-02-28 is 16 workday(s)
from: 2015-02-07 to: 2015-02-22 is 10 workday(s)
from: 2015-02-07 to: 2015-02-23 is 11 workday(s)
from: 2015-02-07 to: 2015-02-24 is 12 workday(s)
from: 2015-02-07 to: 2015-02-25 is 13 workday(s)
from: 2015-02-07 to: 2015-02-26 is 14 workday(s)
from: 2015-02-07 to: 2015-02-27 is 15 workday(s)
from: 2015-02-07 to: 2015-02-28 is 15 workday(s)
我发现 kokizzu 的回答在同一周内(例如太阳到坐着)不起作用,所以改为解决这个问题:
function calcBusinessDays(startDate, endDate) {
var day = moment(startDate);
var businessDays = 0;
while (day.isSameOrBefore(endDate,'day')) {
if (day.day()!=0 && day.day()!=6) businessDays++;
day.add(1,'d');
}
return businessDays;
}
我对 Kokizzu 的回答进行了改编,以解决夏令时问题。在巴西时区 (GMT -3) 中,17/10/2017 和 18/10/2017 之间的差异是 -2.71 而不是 2.
一周的开始时间是 15/10/2017 00:00 UTC 或 14/10/2017 21:00-03:00
周末是 22/10/2017 00:00 UTC 或 21/10/2017 22:00-02:00(夏令时)
因此,"first" 和 "last" 变量之间的天数差异不是 7 天,而是 6 天(或 8 天,具体取决于您所在的时区)。
修复的代码如下:
start = moment(start).utc().add(start.utcOffset(), 'm'); // Ignore timezones
end = moment(end).utc().add(end.utcOffset(), 'm'); // Ignore timezones
var first = start.clone().endOf('week'); // end of first week
var last = end.clone().startOf('week'); // start of last week
// Fixing Summer Time problems
firstCorrection = moment(first).utc().add(60, 'm').toDate(); //
var days = last.diff(firstCorrection,'days') * 5 / 7; // this will always multiply of 7
var wfirst = first.day() - start.day(); // check first week
if(start.day() == 0) --wfirst; // -1 if start with sunday
var wlast = end.day() - last.day(); // check last week
if(end.day() == 6) --wlast; // -1 if end with saturday
return wfirst + days + wlast; // get the total (subtract holidays if needed)
我使用一个简单的函数来完成它。也许不是最有效的,但它确实有效。它不需要 Moment.js。只是 Javascript.
function getNumWorkDays(startDate, endDate) {
var numWorkDays = 0;
var currentDate = new Date(startDate);
while (currentDate <= endDate) {
// Skips Sunday and Saturday
if (currentDate.getDay() !== 0 && currentDate.getDay() !== 6) {
numWorkDays++;
}
currentDate = currentDate.addDays(1);
}
return numWorkDays;
}
为了addDays
,我使用了以下函数:
Date.prototype.addDays = function (days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
};
你可以试试这个(没有循环):
function getBusinessDays(endDate, startDate) {
var lastDay = moment(endDate);
var firstDay = moment(startDate);
let calcBusinessDays = 1 + (lastDay.diff(firstDay, 'days') * 5 -
(firstDay.day() - lastDay.day()) * 2) / 7;
if (lastDay.day() == 6) calcBusinessDays--;//SAT
if (firstDay.day() == 0) calcBusinessDays--;//SUN
return calcBusinessDays;
}
Original Source
通过使用momentjs,可以这样:
private calculateWorkdays(startDate: Date, endDate: Date): number {
// + 1 cause diff returns the difference between two moments, in this case the day itself should be included.
const totalDays: number = moment(endDate).diff(moment(startDate), 'days') + 1;
const dayOfWeek = moment(startDate).isoWeekday();
let totalWorkdays = 0;
for (let i = dayOfWeek; i < totalDays + dayOfWeek; i++) {
if (i % 7 !== 6 && i % 7 !== 0) {
totalWorkdays++;
}
}
return totalWorkdays;
}
我一直在使用一个有用的库moment-business-days加上moment
NPM Link of Moment-business-days
之间的工作日示例const diff = moment('05-15-2017', 'MM-DD-YYYY').businessDiff(moment('05-08-2017','MM-DD-YYYY'));
// diff = 5
工作日应存储在数据库的 table 中并通过 API 提供,无法计算工作日。各国的假期不同,即使在美国每个州也可能有不同的假期,每个公司可能有不同的工作日