// helpers.
function normalizeNameOfWeekday(value) {
return value
.toLowerCase()
.replace(/^(\p{L})(.*)$/u, (_, first, last) =>
[first.toUpperCase(), last].join('')
);
}
function compareWeekdaysByName(a, b) {
const lookup = {
monday: 0, tuesday: 1, wednesday: 2,
thursday: 3, friday: 4,
saturday: 5, sunday: 6,
};
return lookup[a.toLowerCase()] - lookup[b.toLowerCase()];
}
function getTimeScheduleLabel(days) {
const lookup = {
monday_tuesday: 'Monday & Tuesday',
monday_tuesday_wednesday: 'Monday - Wednesday',
monday_tuesday_wednesday_thursday: 'Monday - Thursday',
monday_tuesday_wednesday_thursday_friday: 'All working days',
monday_tuesday_wednesday_thursday_friday_saturday: 'Monday - Saturday',
monday_tuesday_wednesday_thursday_friday_saturday_sunday: 'Every day of the week',
tuesday_wednesday: 'Tuesday & Wednesday',
tuesday_wednesday_thursday: 'Tuesday - Thursday',
tuesday_wednesday_thursday_friday: 'Tuesday - Friday',
tuesday_wednesday_thursday_friday_saturday: 'Tuesday - Saturday',
tuesday_wednesday_thursday_friday_saturday_sunday: 'Tuesday - Sunday',
wednesday_thursday: 'Wednesday & Thursday',
wednesday_thursday_friday: 'Wednesday - Friday',
wednesday_thursday_friday_saturday: 'Wednesday - Saturday',
wednesday_thursday_friday_saturday_sunday: 'Wednesday - Sunday',
thursday_friday: 'Thursday & Friday',
thursday_friday_saturday: 'Thursday - Saturday',
thursday_friday_saturday_sunday: 'Thursday - Sunday',
friday_saturday: 'Friday & Saturday',
friday_saturday_sunday: 'Friday - Sunday',
saturday_sunday: 'All weekend',
};
const scheduleFingerprint = [
// set of unique day-names.
...new Set(days)
]
// ordered list (of unique day-names).
.sort(compareWeekdaysByName)
// comparable schedule-fingerprint.
.join('_').toLowerCase();
return lookup[scheduleFingerprint] ?? days.map(normalizeNameOfWeekday).join(', ');
}
// reducer.
function collectDayOfSameTimeSchedule(index, { day, start_time, end_time }) {
const scheduleKey = `${ start_time } - ${ end_time }`;
// create and/or access the array of
// day-names of the same time-schedule
// and push another matching name into it.
(index[scheduleKey] ??= []).push(day);
return index;
}
// mapper.
function createTimeScheduleFromEntry([scheduleKey, listOfSameTimeScheduleDays]) {
return {
label: getTimeScheduleLabel(listOfSameTimeScheduleDays),
value: scheduleKey,
}
}
const sampleData_01 = [{
day: "monday", start_time: "09:00", end_time: "18:00",
}, {
day: "tuesday", start_time: "09:00", end_time: "18:00",
}, {
day: "wednesday", start_time: "09:00", end_time: "18:00",
}, {
id: 25, day: "thursday", start_time: "09:00", end_time: "18:00",
}, {
day: "friday", start_time: "09:00", end_time: "18:00",
}, {
day: "saturday", start_time: "10:00", end_time: "17:00",
}, {
day: "sunday", start_time: "10:00", end_time: "17:00",
}];
const sampleData_02 = [{
day: "monday", start_time: "09:00", end_time: "20:00",
}, {
day: "tuesday", start_time: "10:00", end_time: "19:00",
}, {
day: "wednesday", start_time: "12:00", end_time: "20:00",
}, {
id: 25, day: "thursday", start_time: "10:00", end_time: "19:00",
}, {
day: "friday", start_time: "10:00", end_time: "17:00",
}, {
day: "saturday", start_time: "10:00", end_time: "17:00",
}, {
day: "sunday", start_time: "10:00", end_time: "17:00",
}];
console.log(
'sample-data with 2 time-schedules ...',
Object
.entries(
sampleData_01
.reduce(collectDayOfSameTimeSchedule, {})
)
.map(createTimeScheduleFromEntry)
);
console.log(
'sample-data with 4 time-schedules ...',
Object
.entries(
sampleData_02
.reduce(collectDayOfSameTimeSchedule, {})
)
.map(createTimeScheduleFromEntry)
);
console.log('\n');
console.log(
'intermediate reducer-step of ... sample-data with 2 time-schedules ...',
sampleData_01
.reduce(collectDayOfSameTimeSchedule, {})
);
console.log(
'intermediate reducer-step of ... sample-data with 4 time-schedules ...',
sampleData_02
.reduce(collectDayOfSameTimeSchedule, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }