Есть ли простой способ получить массив номеров недель по месяцам и годам?

#javascript #date #momentjs #week-number

Вопрос:

Я пытаюсь получить номера недель года в определенном месяце и году с помощью javascript.

 function getWeekNumbers(month, year) {
  var first, last, weeks = [];

  if (month < 10)
    month = "0"   month;

  var date = "01."   month   "."   year;
  first = moment(date, 'dd.MM.yyyy').startOf('month').week();
  last = moment(date, 'dd.MM.yyyy').endOf('month').week();

  for (i = first; i < last; i  ) {
    weeks.push(i);
  }

  return weeks;
}

var result = getWeekNumbers(3, 2021);
console.log(result); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8 M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script> 

Мне нужен такой результат, как; [9,10,11,12,13]

Но код не работает должным образом.

Это также вызовет проблемы в 12-м месяце.

Комментарии:

1. «не работает должным образом» и «вызывает проблемы» не являются хорошими формулировками проблем. Пожалуйста, укажите, каковы выходные данные для данного ввода и чем они отличаются от ожидаемых выходных данных.

Ответ №1:

Ваше решение очень близко, я сделал несколько небольших изменений по своему вкусу, но вы можете изменить это обратно, если хотите.

Прежде всего, я рекомендую использовать isoWeek вместо week , isoWeek соответствует нумерации недель в соответствии с ISO 8601 (https://momentjs.com/docs/#/get-set/iso-week/).

Другая ваша ошибка заключается в том, что вы не включаете last его в цикл for, в этом случае вы хотите включить его, в отличие от обычного, когда вы просто зацикливаетесь на конце списка. Таким образом <= , это то, что вам нужно в for цикле.

 function getWeekNumbers(month,year) {
    var first, last, weeks=[];
    
    first = moment().month(month - 1).year(year).startOf('month').isoWeek();
    last = moment().month(month - 1).year(year).endOf('month').isoWeek();
    
      
    for(var i = first; i <= last; i  ){
      weeks.push(i);
    }
    
    return weeks;
}
 

Комментарии:

1. Код, который дает именно тот результат, который я хочу. Большое спасибо!

Ответ №2:

Удовлетворит ли это то, что вы ищете? Я использовал некоторые функции разделения массивов и даты, чтобы разбить даты любого данного месяца на соответствующие недели:

 const getWeeks = (month, year) => Array(new Date(year, month, 0).getDate()).fill(0).map((_,i) => new Date(year, month-1, i 1)).map((d,i,a) => !i amp;amp; d.getDay() ? [Array(d.getDay()).fill(null), d.getDate()] : d.getDate() === a.length amp;amp; d.getDay() < 6 ? [d.getDate(), Array(6-d.getDay()).fill(null)] : d.getDate()).flat(2).map((d,i,a) => a.length ? a.splice(0,7) : null).filter(w => w);

// February 2021

getWeeks(2, 2021); // -> returns array below ↓↓↓

[
    [null,    1,    2,    3,    4,    5,    6],
    [   7,    8,    9,   10,   11,   12,   13],
    [  14,   15,   16,   17,   18,   19,   20],
    [  21,   22,   23,   24,   25,   26,   27],
    [  28, null, null, null, null, null, null]
]
 

Если вы предпочитаете не null использовать заполнители, а просто иметь более короткие массивы, когда в неделе меньше дней, мы можем добиться этого с помощью дополнительного фильтра. Мы даже можем включить необязательный параметр для этого значения, который, если оставить его пустым (или установить значение неопределенным), приведет к обрезанным массивам:

 const getWeeks = (month, year, nullVal) => Array(new Date(year, month, 0).getDate()).fill(0).map((_,i) => new Date(year, month-1, i 1)).map((d,i,a) => !i amp;amp; d.getDay() ? [Array(d.getDay()).fill(nullVal), d.getDate()] : d.getDate() === a.length amp;amp; d.getDay() < 6 ? [d.getDate(), Array(6-d.getDay()).fill(nullVal)] : d.getDate()).flat(2).map((d,i,a) => a.length ? a.splice(0,7) : null).filter(w => w).map(w => nullVal !== undefined ? w : w.filter(d => d));

// December 2021

getWeeks(12, 2021); // -> bullish value blank :: trimming weeks, returns array below ↓↓↓

[
    [             1,  2,  3,  4],
    [ 5,  6,  7,  8,  9, 10, 11],
    [12, 13, 14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23, 24, 25],
    [26, 27, 28, 29, 30, 31    ]
]

getWeeks(12, 2021, 0); // -> using 0 as nullish value, returns array below ↓↓↓

[
    [ 0,  0,  0,  1,  2,  3,  4],
    [ 5,  6,  7,  8,  9, 10, 11],
    [12, 13, 14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23, 24, 25],
    [26, 27, 28, 29, 30, 31,  0]
]
 

Вы также можете использовать эту функцию, чтобы получить количество недель в месяце или даты на определенной неделе по значению индекса недели:

 // Get number of weeks in month
getWeeks(12, 2021).length // -> 5

// Get dates in a week by index value
getWeeks(5, 2021)[2] // -> [9, 10, 11, 12, 13, 14, 15]
 

Комментарии:

1. Большое спасибо!