Я пытаюсь создать массив месяцев, в котором есть вложенные массивы со всеми днями в этом месяце между диапазоном дат в JavaScript с MomentJS.
цель достижения: если бы мой диапазон дат был с 1 мая по 3 июня
Используя этот цикл, я могу успешно построить массив дней, но я не могу разделить их на месяцы.
while (currentDate <= endDate) {
currentDate.setDate(currentDate.getDate() + 1);
dates.push(new Date(currentDate));[May - month name
1st May - date object for day
2nd May
3rd May
4th May
...]
June
[1st June
2nd June
3rd June]Любая помощь будет оценена по достоинству!
appologies - массив будет содержать все месяцы, которые затем будут содержать все их дни [[1-е 2-е мая ...] [1-е 2-е июня]]
@roblawford, пожалуйста, добавьте точный результат, который вы хотите, к своему вопросу ... Ваш комментарий не содержит «название месяца». И, пожалуйста, убедитесь, что ваш пример имеет правильный синтаксис ...
даты[currentDate.getMonth()].push(currentDate) ?
@DannyHobo, например, это создаст разреженный массив с пустыми элементами 0..3, кроме того, он не добавит название месяца. и если вы нажмете currentDate, все элементы в массиве будут указывать на один и тот же экземпляр даты



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать обычный; ванильный JavaScript без каких-либо библиотек для этого. Библиотека Intl предоставляет API для отображения времени/даты и числовых форматов в зависимости от локали.
const
monthFrmt = new Intl.DateTimeFormat('en', { month: 'long' }),
startDate = new Date('2023-05-01T00:00:00'), // May 1st
endDate = new Date('2023-06-03T00:00:00'), // June 3rd (inclusive)
dateFormatterFn = (date) => `${ordinal(date.getDate())} ${monthFrmt.format(date)}`;
const main = () => {
const dates = generateDates(startDate, endDate, dateFormatterFn);
console.info(dates);
};
const generateDates = (startDate, endDate, dateFormatterFn) => {
const results = [], currDate = new Date(startDate.getTime());
while (currDate <= endDate) {
const key = monthFrmt.format(currDate);
if (results[results.length - 1]?.key !== key) results.push({ key, values: [] });
results[results.length - 1].values.push(dateFormatterFn(currDate));
currDate.setDate(currDate.getDate() + 1);
}
return results.map(Object.values);
}
const rules = new Intl.PluralRules('en', { type: 'ordinal' });
const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
const ordinal = (number) => `${number}${suffixes[rules.select(number)]}`;
main();.as-console-wrapper { top: 0; max-height: 100% !important; }В то время как ваш мне нравится за полноту, мой мне нравится больше, потому что он мой.
Вы можете попробовать что-то вроде этого. Функция для сбора дней между двумя днями, а также для группировки по месяцам (тогда вам нужен и год).
const collectDays = (start, stop) => {
let cursor_mut = start, out = [];
while (cursor_mut <= stop) {
cursor_mut.setDate(cursor_mut.getDate() + 1);
out.push(new Date(cursor_mut));
}
if (start > stop) {
return [out, true];
} else {
return [out, false];
}
};
const groupDays = (dates) => {
let grouped = {};
for (let d of dates) {
let key = JSON.stringify([d.getFullYear(), d.getMonth()]);
if (!grouped[key]) {
grouped[key] = [];
}
grouped[key].push({ year: d.getFullYear(), month: d.getMonth(), day: d.getDate() });
}
return grouped;
};
let startDate = new Date();
let endDate = new Date();
endDate.setDate(endDate.getDate() + 90);
let outArray = [];
let result = collectDays(startDate, endDate, outArray);
console.info(result);
let groupedDates = groupDays(result[0]);
console.info(groupedDates);
Так? Международный формат даты и времени.
let start = new Date("05/01/2023");
let end = new Date("06/15/2023");
let arr = [];
let months = [];
const dayFormatter = new Intl.DateTimeFormat('en-US', {day: "numeric"});
const monthFormatter = new Intl.DateTimeFormat('en-US', {month: 'long'});
while (start <= end) { //get an array of date objects, one per day
arr.push(new Date(start));
start.setDate(start.getDate() + 1);
};
arr.forEach(function(date){ //get array of months
let m = monthFormatter.formatToParts(date).find((o) => o.type == "month").value;
if (!months.includes(m)){
months.push(m);
}
})
months.forEach(function(val,index){ //nest an array in each month
months[index]=[val,[]];
});
months.forEach(function(month){
arr.forEach(function(date){ //fill the nested arrays
let m = monthFormatter.formatToParts(date).find((o) => o.type == "month").value;
if (m === month[0]){
let d = dayFormatter.formatToParts(date).find((o) => o.type == "day").value;
month[1].push(`${ordinal(d)} ${m}`); //IF YOU WANT 1st May format
//month[1].push(date); //IF YOU WANT THE DATE OBJECT INSTEAD
}
});
})
console.info(months)
function ordinal(number) {
const pr = new Intl.PluralRules("en-US", { type: "ordinal" });
const ordinals = {one:'st',two:'nd',few:'rd',many:'th',zero:'th',other:'th'}
return `${number}${ordinals[pr.select(number)]}`;
}Спасибо, приятель - это работает, но вы никогда не получаете первую дату в массиве, всегда начинается со второй даты в массиве...
И вы также получаете дополнительный день в конце всего цикла...
@roblawford только что заметил и исправил это. Должно работать сейчас. Раскомментируйте код, если вам нужен объект даты, как вы сказали в исходном сообщении. Если это работает, пожалуйста, примите. Спасибо.
Ваш пример неясен:
Mayнаходится внутри массива, ноJuneнаходится вне любого массива.