web-dev-qa-db-fra.com

Comment exclure les week-ends entre deux dates à l'aide de Moment.js

J'essaie d'exclure les week-ends dans mon code JavaScript. J'utilise moment.js et j'ai du mal à choisir la bonne variable pour 'jours'.

Jusqu'à présent, j'ai pensé que je devais exclure le jour 6 (samedi) et le jour 0 (dimanche) en modifiant la variable du jour de la semaine pour qu'elle compte uniquement du jour 1 au jour 5. Mais je ne sais pas comment cela change.

Mon jsfiddle est montré ici: 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);
        }
    });
});
26
tman16

Voici!

function addWeekdays(date, days) {
  date = moment(date); // use a clone
  while (days > 0) {
    date = date.add(1, 'days');
    // decrease "days" only if it's a weekday.
    if (date.isoWeekday() !== 6 && date.isoWeekday() !== 7) {
      days -= 1;
    }
  }
  return date;
}

Vous l'appelez comme ça

var date = addWeekdays(moment(), 5);

J'ai utilisé .isoWeekday au lieu de .weekday car cela ne dépend pas de l'environnement local (.weekday(0) peut être soit le lundi soit le dimanche).

Ne soustrayez pas les jours de la semaine, c.-à-d. addWeekdays(moment(), -3) sinon cette fonction simple restera en boucle pour toujours!

Mise à jour de JSFiddle http://jsfiddle.net/Xt2e6/39/ (en utilisant différents momentsjs cdn)

47
acoiro

Ces solutions en boucle d’itération ne répondaient pas à mes besoins . Elles étaient trop lentes pour un grand nombre . J'ai donc créé ma propre version:

https://github.com/leonardosantos/momentjs-business

J'espère que vous le trouverez utile.

21
lsantos

https://github.com/andruhon/moment-weekday-calc plugin for momentJS pourrait être utile pour des tâches similaires

Cela ne résout pas le problème exact, mais il est capable de calculer des jours de semaine spécifiques dans la plage.

Usage:

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)
10
Andrew Kondratev

Je sais que cette question a été postée il y a longtemps, mais au cas où quelqu'un se cognerait dessus, voici une solution optimisée utilisant 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;
}
4
ingbabic

Si vous voulez une version de l'exemple de code de @ acorio performante (avec l'optimisation de @ Isantos) et pouvant traiter des nombres négatifs, utilisez ceci:

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;
};

Voir Fiddle ici: http://jsfiddle.net/dain/5xrr79h0/

4
dain

Je suggérerais d'ajouter une fonction au prototype du moment.

Quelque chose comme ça peut-être? (non testé)

    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;
    },

Et lorsque vous avez terminé et rédigé certains tests, envoyez une demande de tirage pour obtenir des points bonus.

3
Eric Hartford

Si vous voulez une version JavaScript pure (sans compter sur Moment.js), essayez ceci ...

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's the weekend (0=Sun & 6=Sat)
                    }
                    else{
                        counter++;  // It's a weekday so increase the counter
                    }
            }
        }
    return date;
}

Vous l'appelez comme ça ...

var date = addWeekdays(new Date(), 3);

Cette fonction vérifie chaque jour suivant si elle tombe un samedi (jour 6) ou un dimanche (jour 0). Si la valeur est true, le compteur n'est pas encore augmenté, mais la date est augmentée ..__ Ce script convient pour de petits incréments de date d'un mois ou moins.

1
Tremours

d1 et d2 sont des dates de moment passées en tant qu'argument à calculateBusinessDays

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;
}
0
Pekama
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;
}
0
Puzzo