如何将日期数组按月份分组并格式化为含连续日期合并的指定字符串?
Got it, let's walk through how to solve this date grouping and formatting problem step by step—this is a common task when dealing with date datasets, so here's a practical, code-based approach using JavaScript (the logic translates easily to other languages too):
Step 1: Parse Raw Dates into Structured Data
First, we need to turn those string dates (DD.MM.YY) into data we can work with. We'll extract the day, month, and year, then get the month abbreviation (like Sep or Oct) and keep track of the numeric day for later grouping.
const rawDates = ["28.09.21", "30.09.21", "03.10.21", "04.10.21", "05.10.21", "13.10.21"]; // Parse each date into a structured object const parsedDates = rawDates.map(dateStr => { const [day, month, year] = dateStr.split(".").map(Number); // Note: Months are 0-indexed in JavaScript Date objects const fullDate = new Date(2000 + year, month - 1, day); // Get 3-letter month abbreviation (e.g., "Sep") const monthAbbr = fullDate.toLocaleString('en-US', { month: 'short' }); return { monthAbbr, day: Number(day) }; });
Step 2: Group Dates by Month
Next, we'll group all dates by their month abbreviation. We'll also sort the days in each group to ensure we can correctly identify consecutive dates later.
// Group dates into a { [monthAbbr]: [days] } object const groupedByMonth = parsedDates.reduce((groups, date) => { const { monthAbbr, day } = date; if (!groups[monthAbbr]) { groups[monthAbbr] = []; } groups[monthAbbr].push(day); // Sort days numerically to catch consecutive sequences groups[monthAbbr].sort((a, b) => a - b); return groups; }, {});
Step 3: Merge Consecutive Days
This is the core logic—we'll take each sorted list of days and merge consecutive numbers into a start-end format. For non-consecutive days, we'll keep them as individual values.
// Helper function to merge consecutive days function mergeConsecutiveDays(days) { if (days.length === 0) return []; const merged = []; let startDay = days[0]; let endDay = days[0]; for (let i = 1; i < days.length; i++) { const currentDay = days[i]; // Check if current day is consecutive to the previous end if (currentDay === endDay + 1) { endDay = currentDay; } else { // Add the current group to results merged.push(startDay === endDay ? `${startDay}` : `${startDay}-${endDay}`); startDay = currentDay; endDay = currentDay; } } // Add the final group merged.push(startDay === endDay ? `${startDay}` : `${startDay}-${endDay}`); return merged; } // Apply merging to each month group const formattedMonthGroups = Object.entries(groupedByMonth).map(([month, days]) => { const mergedDays = mergeConsecutiveDays(days); return `${month}: ${mergedDays.join(", ")}`; });
Step 4: Build the Final Output String
Finally, we'll combine the formatted month groups into the exact string format you need:
const finalOutput = `[${formattedMonthGroups.join("; ")}]`; console.log(finalOutput); // Outputs: [Sep: 28, 30; Oct: 3-5, 13]
Bonus Notes
- Duplicate Dates: If your raw array might have duplicates, add a check before pushing days to the group (e.g.,
if (!groups[monthAbbr].includes(day)) groups[monthAbbr].push(day)). - Year Handling: This example assumes years are 20xx. If you need to handle other years, adjust the
new Date()call to use the correct full year. - Localization: To get month abbreviations in other languages, change the
toLocaleStringlocale (e.g.,'de-DE'for German,'fr-FR'for French).
内容的提问来源于stack exchange,提问作者Bugrym

