2015-08-24 1 views
4

J'essaie d'obtenir le nième jour de la semaine — par exemple, le deuxième dimanche — d'un mois dans lequel une certaine date tombe.Obtenez un jour de la semaine donné dans un mois donné avec JavaScript

Par exemple, si la date est le 24 Août, 2015, je voudrais faire:

nthDayOfMonth(0, 2, new Date(2015, 7, 24)) 

et obtenir 9 Août 2015 (2e dimanche d'Août). J'aimerais ensuite ajouter un mois à la date, rappeler la fonction et obtenir le 13 septembre 2015 (2e dimanche de septembre).

Pour une raison quelconque, le code ci-dessous ne fonctionne pas.

Qu'est-ce qui me manque?

function nthDayOfMonth(day, n, date) {                        
    console.log(day); 
    console.log(n); 
    var count = 0; 
    var idate = new Date(date);                          

    idate.setDate(1);                             

    while ((count) < n) {                            
     idate.setDate(idate.getDate() + 1); 
     if (idate.getDay() == day) { 
     count++;                              
     }                                
    }                                 

return idate;                              

}

+0

Avez-vous pris en considération le fait que le mois est 0 base (par exemple Août == 7) –

+0

, je pense aussi aujourd'hui est en fait 24/08/15, non 24.09.15. – aaplmath

+0

Wow .... Il calculait les choses correctement, je ne lisais pas la calculatrice correctement. –

Répondre

5

Vous devez vérifier idate.getDay() avant d'incrémenter le jour du mois. Sinon, vous obtiendrez une réponse incorrecte si le jour de la semaine souhaité tombe le premier jour du mois.

L'extrait suivant illustre la fonction corrigée.

function print(s) { 
 
    document.write(s + '<br />'); 
 
} 
 

 
function nthWeekdayOfMonth(weekday, n, date) { 
 
    var count = 0, 
 
     idate = new Date(date.getFullYear(), date.getMonth(), 1); 
 
    while (true) { 
 
    if (idate.getDay() === weekday) { 
 
     if (++count == n) { 
 
     break; 
 
     } 
 
    } 
 
    idate.setDate(idate.getDate() + 1); 
 
    } 
 
    return idate; 
 
} 
 

 
      // Second Sunday of the current month. 
 
var date = new Date(); 
 
print(date = nthWeekdayOfMonth(0, 2, date)); 
 
      // Second Sunday of next month. 
 
date.setMonth(date.getMonth() + 1); 
 
print(date = nthWeekdayOfMonth(0, 2, date)); 
 

 
      // First Tuesday of September 2015. 
 
print(nthWeekdayOfMonth(2, 1, new Date(2015, 8))); 
 
      // First Wednesday of September 2015. 
 
print(nthWeekdayOfMonth(3, 1, new Date(2015, 8))); 
 
      // Second Tuesday of September 2015. 
 
print(nthWeekdayOfMonth(2, 2, new Date(2015, 8))); 
 
      // Second Wednesday of September 2015. 
 
print(nthWeekdayOfMonth(3, 2, new Date(2015, 8)));
body { 
 
    font-family: sans-serif; 
 
}

Il y a une approche encore mieux qui calcule la date souhaitée sans boucle. Nous commençons par considérer le jour de la semaine du premier jour du mois. Supposons que c'est un samedi, que JavaScript appelle 6, et que vous cherchez un dimanche, qui est 0.

Pour obtenir le premier dimanche du mois, vous devez avancer la date de ce nombre de jours:

0 - 6 + 7 

Le résultat est 1. Comment fonctionne le calcul? 0 - 6 est le nombre de jours depuis le jour de la semaine 6 jusqu'au jour de la semaine 0, et pour transformer une valeur négative en jour de semaine valide, nous ajoutons 7.

En général, le nombre de jours de semaine a à jour de la semaine b est

(b - a + 7) % 7 

Pour poursuivre l'exemple, supposons que nous voulions que le premier dimanche du mois. Dans ce cas, nous sommes arrivés. Mais si nous voulons le deuxième jour du mois, nous devons avancer la date de 7 jours de plus. En général, donné n tel que n == 1 signifie la première occurrence d'un jour de la semaine donné, nous devons avancer de (n - 1) * 7 jours.

Pour mettre tout cela ensemble, si date est le premier jour du mois, on peut se rendre à l'apparition n ème weekday en avançant

(weekday - date.getDay() + 7) % 7 + (n - 1) * 7 

ces derniers jours le premier jour du mois.

Cette approche est implémentée ci-dessous.

function print(s) { 
 
    document.write(s + '<br />'); 
 
} 
 

 
function nthWeekdayOfMonth(weekday, n, date) { 
 
    var date = new Date(date.getFullYear(), date.getMonth(), 1), 
 
     add = (weekday - date.getDay() + 7) % 7 + (n - 1) * 7; 
 
    date.setDate(1 + add); 
 
    return date; 
 
} 
 

 
      // Second Sunday of the current month. 
 
var date = new Date(); 
 
print(date = nthWeekdayOfMonth(0, 2, date)); 
 
      // Second Sunday of next month. 
 
date.setMonth(date.getMonth() + 1); 
 
print(date = nthWeekdayOfMonth(0, 2, date)); 
 

 
      // First Tuesday of September 2015. 
 
print(nthWeekdayOfMonth(2, 1, new Date(2015, 8))); 
 
      // First Wednesday of September 2015. 
 
print(nthWeekdayOfMonth(3, 1, new Date(2015, 8))); 
 
      // Second Tuesday of September 2015. 
 
print(nthWeekdayOfMonth(2, 2, new Date(2015, 8))); 
 
      // Second Wednesday of September 2015. 
 
print(nthWeekdayOfMonth(3, 2, new Date(2015, 8)));
body { 
 
    font-family: sans-serif; 
 
}

+0

N'est-ce pas l'équivalent fonctionnel de la commutation de l'ordre de l'instruction if et de l'incrément de date? –

+0

Si vous deviez changer l'ordre de l'instruction if et de l'opération d'incrémentation, vous devez incrémenter la date avant de passer au test en tête de la boucle. Vous ne pouvez pas incrémenter la date avant de tester si 'count

1

Votre code semble fonctionner très bien. Pour ajouter un mois, vous pouvez utiliser d.setMonth(d.getMonth()+1).

Essayez cette démo:

function nthDayOfMonth(day, n, date) { 
 
\t var count = 0, 
 
\t  idate = new Date(date); 
 
\t idate.setDate(1); 
 

 
\t while (count < n) { 
 
\t \t idate.setDate(idate.getDate() + 1); 
 
\t \t if (idate.getDay() == day) { count++; } 
 
\t } 
 

 
\t return idate; 
 
} 
 

 
// Today : 2015-08-24 
 
var today = new Date(); 
 

 
// Second Sunday of current month : 2015-08-09 
 
var res = nthDayOfMonth(0, 2, today); 
 

 
// res plus 1 month : 2015-09-09 (Wednesday) 
 
var plusOne = new Date(res); 
 
plusOne.setMonth(plusOne.getMonth() + 1); 
 

 
// Second Sunday of next month : 2015-09-13 
 
var res2 = nthDayOfMonth(0, 2, plusOne); 
 

 
document.body.innerHTML = 'Today is <br>' + today + '<br>' 
 
         + 'Second Sunday of current month is <br>' + res + '<br>' 
 
         + 'If you add a month to it, you get <br>' + plusOne + '<br>' 
 
         + 'And second Sunday of that month is <br>' + res2;

0

Je viens d'ajouter un tweak à l'excellente réponse de Michael Laszlo pour permettre à l'appelant de fournir n == 5 (ou une plus grande valeur) pour indiquer que le dernier jour de la semaine du mois est souhaitée :

function nthWeekdayOfMonth(weekday, n, date) { 
    var month = date.getMonth(); 
    var date = new Date(date.getFullYear(), month, 1), 
     add = (weekday - date.getDay() + 7) % 7 + (n - 1) * 7; 

    // make sure that we stay in the same month 
    do { 
    date.setMonth(month); 
    date.setDate(1 + add); 
    add -= 7; 
    } while (date.getMonth() != month); 

    return date; 
}