Moment.js, как получить неделю месяца? (стиль календаря Google)

Я использую Moment.js, и это здорово. Проблема, которую я имею сейчас, заключается в том, что я не могу понять, как получить неделю месяца определенной даты. Я могу найти "неделю года" в Moment js docs. Например, если я выберу сегодня дату (2/12/2014), я хотел бы знать, что эта дата находится на второй неделе этого месяца февраля, и, следовательно, это вторая среда месяца. Любые идеи?

EDIT: Я предполагаю, что необходимо уточнение. То, что мне больше всего нужно, - это n-й номер определенного дня в месяц. Например, (из комментариев) 1 февраля 2014 года будет первая суббота месяца. 3 февраля 2014 года будет первым понедельником месяца, даже если он "технически" второй недели месяца. В принципе, точно, как функция повторения календаря Google классифицирует дни.

Ответ 1

Кажется, что moment.js не имеет метода, который реализует функциональность, которую вы ищете. Тем не менее, вы можете найти n-й номер определенного дня недели в месяц, используя Math.ceil date / 7 Например:

var firstFeb2014 = moment("2014-02-01"); //saturday
var day = firstFeb2014.day(); //6 = saturday
var nthOfMoth = Math.ceil(firstFeb2014.date() / 7); //1

var eightFeb2014 = moment("2014-02-08"); //saturday, the next one
console.log( Math.ceil(eightFeb2014.date() / 7) ); //prints 2, as expected

Похоже, это номер, который вы ищете, о чем свидетельствует следующий тест

function test(mJsDate){
   var str = mJsDate.toLocaleString().substring(0, 3) +
             " number " + Math.ceil(mJsDate.date() / 7) +
             " of the month";
   return str;
}

for(var i = 1; i <= 31; i++) {
   var dayStr = "2014-01-"+ i;
   console.log(dayStr + " " + test(moment(dayStr)) );
}

//examples from the console:
//2014-01-8 Wed number 2 of the month
//2014-01-13 Mon number 2 of the month
//2014-01-20 Mon number 3 of the month
//2014-01-27 Mon number 4 of the month
//2014-01-29 Wed number 5 of the month

Ответ 2

При расчете недели месяца, основанного на заданной дате, вы должны учитывать смещение. Не все месяцы начинаются в первый день недели.

Если вы хотите учесть это смещение, вы можете использовать что-то вроде следующего, если вы используете момент.

function weekOfMonth (input = moment()) {
  const firstDayOfMonth = input.clone().startOf('month');
  const firstDayOfWeek = firstDayOfMonth.clone().startOf('week');

  const offset = firstDayOfMonth.diff(firstDayOfWeek, 'days');

  return Math.ceil((input.date() + offset) / 7);
}

Ответ 3

Простое использование moment.js

function week_of_month(date) {

        prefixes = [1,2,3,4,5];

    return prefixes[0 | moment(date).date() / 7] 

}

Ответ 5

Я думаю, что ответ на этот вопрос будет полезен, хотя он не использует moment.js по запросу:

Получить неделю месяца

Ответ 6

function countWeekdayOccurrencesInMonth(date) {

    var m = moment(date),
            weekDay = m.day(),
            yearDay = m.dayOfYear(),
            count = 0;

    m.startOf('month');
    while (m.dayOfYear() <= yearDay) { 
        if (m.day() == weekDay) {
            count++; 
        }
        m.add('days', 1); 
    }

    return count;
}

Ответ 7

Существует проблема с ответом @Daniel Earwicker. Я использовал свою функцию в своем приложении, и цикл while был бесконечным из-за следующей ситуации:

Я пытался выяснить, какой неделе декабря (2016) был 31-й день. в первый день декабря был день 336 года. Последний день декабря был днем ​​366 года.

Проблема здесь: когда наступил день 366 (31 декабря, последний день года), код добавил еще один день к этой дате. Но с другой день добавил, что это будет 1-й день января 2017 года. Поэтому цикл так и не закончился.

 while (m.dayOfYear() <= yearDay) { 

    if (m.day() == weekDay) {
        count++; 
    }
    m.add('days', 1); 
}

Я добавил следующие строки в код, чтобы проблема была исправлена:

function countWeekdayOccurrencesInMonth(date) {

  var m = moment(date),
        weekDay = m.day(),
        yearDay = m.dayOfYear(),
        year = m.year(),
        count = 0;

 m.startOf('month');

 while (m.dayOfYear() <= yearDay && m.year() == year) {
    if (m.day() == weekDay) {
        count++;
    }
    m.add('days', 1);
 }

 return count;
}

Он проверяет, находится ли он в том же году с даты, когда он был ограничен.

Ответ 8

Что-то вроде:

weekOfCurrentMonth = (moment().week() - (moment().month()*4));

Это занимает текущую неделю года и вычитает ее в 4 раза больше, чем в предыдущие месяцы. Что должно дать вам неделю текущего месяца

Ответ 9

Здесь решение Robin Malfait реализовано с помощью облегченной библиотеки date-fns

import {
    differenceInDays,
    startOfMonth,
    startOfWeek,
    getDate
} from 'date-fns'

const weekOfMonth = function (date) {
    const firstDayOfMonth = startOfMonth(date)
    const firstDayOfWeek = startOfWeek(firstDayOfMonth)
    const offset = differenceInDays(firstDayOfMonth, firstDayOfWeek)
    return Math.ceil((getDate(date) + offset) / 7)
}

export default weekOfMonth

Ответ 10

Я бы сделал следующее:

let todaysDate = moment(moment.now());
let endOfLastMonth = moment(get(this, 'todaysDate')).startOf('month').subtract(1, 'week');

let weekOfMonth = todaysDate.diff(endOfLastMonth, 'weeks');

Он получает todaysDate и endOfLastMonth а затем использует встроенный метод Moment diff() для вычисления номера недели текущего месяца.