Как исключить выходные дни между двумя датами, используя Moment.js
Я пытаюсь исключить выходные дни в своем JavaScript-коде. Я использую moment.js и с трудом выбираю правильную переменную для "дней".
До сих пор я думал, что мне нужно исключить день 6 (субботу) и день 0 (воскресенье), изменив переменную дня недели, чтобы считать только с 1-го дня до 5-го дня. Но не знаю, как это изменится.
Мой jsfiddle показан здесь: FIDDLE
HTML
<div id="myContent">
<input type="radio" value="types" class="syncTypes" name="syncTypes"> <td><label for="xshipping.xshipping1">Free Shipping: (<span id="fsv1" value="5">5</span> to <span id="fsv2" value="10">10</span> working days)</label> </td><br>
<div id="contacts" style="display:none;border:1px #666 solid;padding:3px;top:15px;position:relative;margin-bottom:25px;">
Contacts
</div>
<input type="radio" value="groups" class="syncTypes" name="syncTypes"> <td><label for="xshipping.xshipping2">Express Shipping: (<span id="esv1" value="3">3</span> to <span id="esv2" value="4">4</span> working days)</label> </td>
<div id="groups" style="display:none;border:1px #666 solid;padding:3px;top:15px;position:relative">
Groups
</div>
</div>
JavaScript
var a = 5; //Free shipping between a
var b = 10;//and b
var c = 3;//Express shipping between c
var d = 4;//and d
var now = moment();
var f = "Your item will be delivered between " + now.add("days",a).format("Do MMMM") + " and " + now.add("days",b).format("Do MMMM");
var g = "Your item will be delivered between " + now.add("days".c).format("Do MMMM") + " and " + now.add("days",d).format("Do MMMM");
var h = document.getElementById('contacts');
h.innerHTML = g
var i = document.getElementById('groups');
i.innerHTML = f
$(function() {
$types = $('.syncTypes');
$contacts = $('#contacts');
$groups = $('#groups');
$types.change(function() {
$this = $(this).val();
if ($this == "types") {
$groups.slideUp(300);
$contacts.delay(200).slideDown(300);
}
else if ($this == "groups") {
$contacts.slideUp(300);
$groups.delay(200).slideDown(300);
}
});
});
Ответы
Ответ 1
Здесь вы идете!
function addWeekdays(date, days) {
date = moment(date); // use a clone
while (days > 0) {
date = date.add(1, 'days');
// decrease "days" only if it a weekday.
if (date.isoWeekday() !== 6 && date.isoWeekday() !== 7) {
days -= 1;
}
}
return date;
}
Вы называете это
var date = addWeekdays(moment(), 5);
Я использовал .isoWeekday
вместо .weekday
, потому что он не зависит от языкового стандарта (.weekday(0)
может быть как в понедельник, так и в воскресенье).
Не вычитайте дни недели, т.е. addWeekdays(moment(), -3)
в противном случае эта простая функция будет зацикливаться навсегда!
Обновлен JSFiddle http://jsfiddle.net/Xt2e6/39/ (с использованием разных momentjs cdn)
Ответ 2
Те итерационные петлевые решения не соответствовали моим потребностям.
Они были слишком медленными для больших чисел.
Поэтому я сделал свою собственную версию:
https://github.com/leonardosantos/momentjs-business
Надеюсь, вы сочтете это полезным.
Ответ 3
https://github.com/andruhon/moment-weekday-calc плагин для momentJS может быть полезен для подобных задач
Он не решает точной проблемы, но он способен вычислять конкретные дни недели в диапазоне.
Использование:
moment().isoWeekdayCalc({
rangeStart: '1 Apr 2015',
rangeEnd: '31 Mar 2016',
weekdays: [1,2,3,4,5], //weekdays Mon to Fri
exclusions: ['6 Apr 2015','7 Apr 2015'] //public holidays
}) //returns 260 (260 workdays excluding two public holidays)
Ответ 4
Если вам нужна версия примера кода @acorio, которая является результативной (с использованием оптимизации @Isantos) и может обрабатывать отрицательные числа, используйте это:
moment.fn.addWorkdays = function (days) {
var increment = days / Math.abs(days);
var date = this.clone().add(Math.floor(Math.abs(days) / 5) * 7 * increment, 'days');
var remaining = days % 5;
while(remaining != 0) {
date.add(increment, 'days');
if(date.isoWeekday() !== 6 && date.isoWeekday() !== 7)
remaining -= increment;
}
return date;
};
Смотрите здесь Fiddle: http://jsfiddle.net/dain/5xrr79h0/
Ответ 5
Я знаю, что этот вопрос был опубликован давно, но на случай, если кто-то столкнется с этим, вот оптимизированное решение, используя moment.js:
function getBusinessDays(startDate, endDate){
var startDateMoment = moment(startDate);
var endDateMoment = moment(endDate)
var days = Math.round(startDateMoment.diff(endDateMoment, 'days') - startDateMoment .diff(endDateMoment, 'days') / 7 * 2);
if (endDateMoment.day() === 6) {
days--;
}
if (startDateMoment.day() === 7) {
days--;
}
return days;
}
Ответ 6
Я бы предложил добавить функцию к прототипу момента.
Что-то вроде этого, может быть? (Непроверенные)
nextWeekday : function () {
var day = this.clone(this);
day = day.add('days', 1);
while(day.weekday() == 0 || day.weekday() == 6){
day = day.add("days", 1);
}
return day;
},
nthWeekday : function (n) {
var day = this.clone(this);
for (var i=0;i<n;i++) {
day = day.nextWeekday();
}
return day;
},
И когда вы закончите и напишите несколько тестов, отправьте запрос на получение бонусных баллов.
Ответ 7
Если вы хотите использовать чистую версию JavaScript (не полагаясь на Moment.js), попробуйте это...
function addWeekdays(date, days) {
date.setDate(date.getDate());
var counter = 0;
if(days > 0 ){
while (counter < days) {
date.setDate(date.getDate() + 1 ); // Add a day to get the date tomorrow
var check = date.getDay(); // turns the date into a number (0 to 6)
if (check == 0 || check == 6) {
// Do nothing it the weekend (0=Sun & 6=Sat)
}
else{
counter++; // It a weekday so increase the counter
}
}
}
return date;
}
Вы называете это так...
var date = addWeekdays(new Date(), 3);
Эта функция проверяет каждый следующий день, чтобы узнать, попадает ли она в субботу (6 день) или воскресенье (день 0). Если значение true, счетчик не увеличивается, но дата увеличивается.
Этот script отлично подходит для небольших дат, таких как месяц или менее.
Ответ 8
const calcBusinessDays = (d1, d2) => {
// Calc all days used including last day ( the +1 )
const days = d2.diff(d1, 'days') + 1;
console.log('Days:', days);
// how many full weekends occured in this time span
const weekends = Math.floor( days / 7 );
console.log('Full Weekends:', weekends);
// Subtract all the weekend days
let businessDays = days - ( weekends * 2);
// Special case for weeks less than 7
if( weekends === 0 ){
const cur = d1.clone();
for( let i =0; i < days; i++ ){
if( cur.day() === 0 || cur.day() === 6 ){
businessDays--;
}
cur.add(1, 'days')
}
} else {
// If the last day is a saturday we need to account for it
if (d2.day() === 6 ) {
console.log('Extra weekend day (Saturday)');
businessDays--;
}
// If the first day is a sunday we need to account for it
if (d1.day() === 0) {
console.log('Extra weekend day (Sunday)');
businessDays--;
}
}
console.log('Business days:', businessDays);
return businessDays;
}
Ответ 9
d1 и d2 - даты моментов
calculateBusinessDays(d1, d2) {
const days = d2.diff(d1, "days") + 1;
let newDay: any = d1.toDate(),
workingDays: number = 0,
sundays: number = 0,
saturdays: number = 0;
for (let i = 0; i < days; i++) {
const day = newDay.getDay();
newDay = d1.add(1, "days").toDate();
const isWeekend = ((day % 6) === 0);
if (!isWeekend) {
workingDays++;
} else {
if (day === 6) saturdays++;
if (day === 0) sundays++;
}
}
console.log("Total Days:", days, "workingDays", workingDays, "saturdays", saturdays, "sundays", sundays);
return workingDays;
}