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]
}
Ответ 4
В этой библиотеке добавлена функция moment.weekMonth()
https://github.com/c-trimm/moment-recur
Ответ 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()
для вычисления номера недели текущего месяца.