I am having a date list like below
let dates = ["2022-12-20", "2022-12-21", "2022-12-22", "2022-12-27", "2022-12-30","2022-12-31", "2023-01-01"];
I would like to convert the date array to a range of dates, as shown in the below output
let result = ["20 Dec - 22 Dec", "27 Dec 2022", "30 Dec - 1 Jan "];
Below is my code:
fun(dates)
{
let startDate = this.dates[0], endDateIndex = - 1, finalDateString = "", arr = [];
for (let i = 1; i < dates.length; i ) {
if (moment(startDate).add(i, 'days').format("YYYY-MM-DD") == moment(dates[i]).format("YYYY-MM-DD")) {
endDateIndex = i;
}
else {
finalDateString = endDateIndex > 0 ? moment(startDate).format("DD MMM") " - "
moment(dates[endDateIndex]).format("DD MMM") : '';
if (endDateIndex == -1) {
finalDateString = finalDateString " " moment(startDate).format("DD MMM") ","
}
startDate = dates[i];
endDateIndex = -1;
}
}
arr.push(finalDateString);
return arr;
}
In my code, I am getting the wrong result in the date range. Kindly guide me to build logic.
CodePudding user response:
You could reduce your dates into date ranges first:
[
{ "start": "2022-12-20", "end": "2022-12-22" },
{ "start": "2022-12-27" },
{ "start": "2022-12-30", "end": "2023-01-01" }
]
Then format the ranges afterwards.
const dates = [
"2022-12-20", "2022-12-21", "2022-12-22",
"2022-12-27",
"2022-12-30", "2022-12-31", "2023-01-01"
];
const parseDate = (date) => moment(date, 'YYYY-MM-DD');
const pushOrSetEnd = (results, last, prev, curr) => {
if (moment.duration(parseDate(curr).diff(parseDate(prev))).asDays() <= 1) {
last.end = curr;
} else {
results.push({ start: curr });
}
};
const reduceDatesIntoRanges = (dates) =>
dates.slice(1).reduce((acc, date) => {
const last = acc[acc.length - 1];
pushOrSetEnd(acc, last, last.end ? last.end : last.start, date);
return acc;
}, [{ start: dates[0] }]);
const dateRanges = reduceDatesIntoRanges(dates);
const formatDateWithYear = (date) => parseDate(date).format('D MMM YYYY');
const formatDate = (date) => parseDate(date).format('D MMM');
const formatDateRange = ({ start, end }) => `${formatDate(start)} - ${formatDate(end)}`;
const formattedDateRanges = dateRanges.map(dateRange =>
!dateRange.end ? formatDateWithYear(dateRange.start) : formatDateRange(dateRange));
console.log(formattedDateRanges);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<!--
const expected = [
"20 Dec - 22 Dec",
"27 Dec 2022",
"30 Dec - 1 Jan"
];
-->
CodePudding user response:
Maybe this will work for you
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script>
let dates = ["2022-12-20", "2022-12-21", "2022-12-22", "2022-12-27", "2022-12-30","2022-12-31", "2023-01-01"];
let expectedResult = ["20 Dec - 22 Dec", "27 Dec 2022", "30 Dec - 1 Jan "];
function organizePeriods(dates) {
let startDate = dates[0], endDateIndex = - 1, finalDateString = "", arr = [], periodLength = 1;
for (let i = 1; i < dates.length; i ) {
if (moment(startDate).add(periodLength, 'days').format("YYYY-MM-DD") === moment(dates[i]).format("YYYY-MM-DD")) {
periodLength ;
endDateIndex = i;
if (i < dates.length - 1) {
continue
}
}
if (endDateIndex > 0) {
finalDateString = moment(startDate).format("DD MMM") " - " moment(dates[endDateIndex]).format("DD MMM");
} else if (endDateIndex === -1) {
finalDateString = moment(startDate).format("DD MMM")
}
arr.push(finalDateString);
startDate = dates[i];
endDateIndex = -1;
periodLength = 1;
finalDateString = ""
}
return arr;
}
console.log("result", organizePeriods(dates));
console.log("expected result", expectedResult);
</script>