Создайте массив месяцев с вложенными днями между диапазоном дат

Я пытаюсь создать массив месяцев, в котором есть вложенные массивы со всеми днями в этом месяце между диапазоном дат в JavaScript с MomentJS.

цель достижения: если бы мой диапазон дат был с 1 мая по 3 июня

Используя этот цикл, я могу успешно построить массив дней, но я не могу разделить их на месяцы.

while (currentDate <= endDate) {
currentDate.setDate(currentDate.getDate() + 1);
dates.push(new Date(currentDate));
This is pretty much what i want to achieve:

[May - month name
1st May - date object for day
2nd May
3rd May
4th May
...]
June
[1st June
2nd June
3rd June]

Любая помощь будет оценена по достоинству!

Ваш пример неясен: May находится внутри массива, но June находится вне любого массива.

Heiko Theißen 19.05.2023 16:02

appologies - массив будет содержать все месяцы, которые затем будут содержать все их дни [[1-е 2-е мая ...] [1-е 2-е июня]]

roblawford 19.05.2023 16:05

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

derpirscher 19.05.2023 16:05

даты[currentDate.getMonth()].push(currentDate) ?

Danny Hobo 19.05.2023 16:05

@DannyHobo, например, это создаст разреженный массив с пустыми элементами 0..3, кроме того, он не добавит название месяца. и если вы нажмете currentDate, все элементы в массиве будут указывать на один и тот же экземпляр даты

derpirscher 19.05.2023 16:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
5
81
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать обычный; ванильный 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; }

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

Ronnie Royston 19.05.2023 18:27

Вы можете попробовать что-то вроде этого. Функция для сбора дней между двумя днями, а также для группировки по месяцам (тогда вам нужен и год).

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);

https://jsfiddle.net/xpz43rog/1

Ответ принят как подходящий

Так? Международный формат даты и времени.

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 22.05.2023 11:02

И вы также получаете дополнительный день в конце всего цикла...

roblawford 22.05.2023 15:08

@roblawford только что заметил и исправил это. Должно работать сейчас. Раскомментируйте код, если вам нужен объект даты, как вы сказали в исходном сообщении. Если это работает, пожалуйста, примите. Спасибо.

Ronnie Royston 25.05.2023 05:46

Другие вопросы по теме