Home > Net >  How would I simplify an object containing "working hours"?
How would I simplify an object containing "working hours"?

Time:12-10

I've got an object with the office hours / working hours specified for each day of the week. My objective is to be able to simplify the textual output of the object without the need for repeating unnecessary days' working hours that are the same as the previous day's working hours.

The current output is as followed:

Monday: 08:00 AM - 21:00 PM
Tuesday: 08:00 AM - 21:00 PM
Wednesday: 08:00 AM - 21:00 PM
Thursday: 08:00 AM - 21:00 PM
Friday: 08:00 AM - 21:00 PM
Saturday: 08:00 AM - 18:00 PM

I'm doing the following to display the textual output of the working hours for each day (it should skip any days with the start and end time set to 00:00 AM - such as Sunday):

// Office hours object
const json_office_hours = '{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}';
const office_hours = JSON.parse(json_office_hours);


// Iteration
let office_hours_text = "";
let oh_prev_day = "Monday";
for (let day in office_hours) {
  if (office_hours.hasOwnProperty(day)) {
    let oh_start = office_hours[day].start;
    let oh_end = office_hours[day].end;

    if (oh_start !== '00:00 AM' && oh_end !== '00:00 AM') {
      office_hours_text  = day   ": "   oh_start   " - "   oh_end   '\n';
    }
    oh_prev_day = day;
  }
}

console.log(office_hours_text);

The simplified output I'm trying to achieve, is the following:

Monday - Friday: 08:00 AM - 21:00 PM
Saturday: 08:00 AM - 18:00 PM

For some reason, I cannot wrap my head around simplifying the output.

Your assistance would be greatly appreciated - and thank you.

CodePudding user response:

You can group it by concatenated string between oh_start and oh_end and use array to save what days have those working hours. From there on is only to loop through grouped elements and format the text. If only one day is present with thouse working hours just don't show the last element

// Iteration
function GroupWorkingDays(json_office_hours) {
    const office_hours = JSON.parse(json_office_hours);
    let office_hours_text = [];
    let group_by_working = {};
    let lastGroup = false;
    let index = 0;
    for (let day in office_hours) {
        if (office_hours.hasOwnProperty(day)) {
            let oh_start = office_hours[day].start;
            let oh_end = office_hours[day].end;

            if (oh_start !== '00:00 AM' && oh_end !== '00:00 AM') {
                if (!lastGroup)
                    lastGroup = oh_start   oh_end;
                let currentGroup = oh_start   oh_end;
                if (lastGroup !== currentGroup) {
                    index  ;
                    lastGroup = currentGroup;
                }
                if (!group_by_working[index])
                    group_by_working[index] = {start: oh_start, end: oh_end, days: []};
                group_by_working[index].days.push(day);
            }
        }
    }

    for (key in group_by_working) {
        let group = group_by_working[key];
        if (group.days.length > 1) {
            office_hours_text.push(group.days[0]   " - "   group.days.slice(-1)   " : "   group.start   " - "   group.end);
        } else {
            office_hours_text.push(group.days[0]   " : "   group.start   " - "   group.end);
        }
    }
    console.log(office_hours_text.join("\n"));
}
console.log("OP example");
GroupWorkingDays('{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}');
console.log("pilchard  example");
GroupWorkingDays('{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"10:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}');

CodePudding user response:

What you can do is group the days as you loop over them, and at the moment you find the end of a group add it to the text

Since that solution prints when it loop on the day after the break, you need to have code after the loop to print the last group

// Office hours object
const json_office_hours = '{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}';
const office_hours = JSON.parse(json_office_hours);

// Iteration
let office_hours_text = "";
let oh_group = {
  start_day: "Monday",
  end_day: "Monday",
  start: office_hours.Monday.start,
  end: office_hours.Monday.end
}

for(let day in office_hours) {
    if(office_hours.hasOwnProperty(day)) {
        let oh_start = office_hours[day].start;
        let oh_end = office_hours[day].end;
        
        if (oh_start === oh_group.start && oh_end === oh_group.end) {
            // add to the group
            oh_group.end_day = day;
        } else {
            // add to the text
            if(oh_group.start !== '00:00 AM' && oh_group.end !== '00:00 AM') {
                if (oh_group.start_day === oh_group.end_day) {
                    office_hours_text  = oh_group.start_day;
                } else {
                    office_hours_text  = oh_group.start_day   " - "   oh_group.end_day;
                }
                office_hours_text  = ": "   oh_group.start   " - "   oh_group.end   '\n';
            }
            // and reset the group
            oh_group = {
                start_day: day,
                end_day: day,
                start: office_hours[day].start,
                end: office_hours[day].end
            };
        }
    }
}
// since the loop prints when it finds the end of a group, 
// the last group needs to be printed outside of the loop
if(oh_group.start !== '00:00 AM' && oh_group.end !== '00:00 AM') {
    if (oh_group.start_day === oh_group.end_day) {
        office_hours_text  = oh_group.start_day;
    } else {
        office_hours_text  = oh_group.start_day   " - "   oh_group.end_day;
    }
    office_hours_text  = ": "   oh_group.start   " - "   oh_group.end   '\n';
}

console.log(office_hours_text);

CodePudding user response:

I would start simple, by grouping the days by their working hours. From there, you can further simplify the days that show up. Press the buttons to see several possible combinations. It also works when Wednesday is for example closed.

function parseHours(officeHours) {
  // A mapping of office hours to the days to which they are appliccable
  const officeHourDays = {};
  Object.entries(officeHours).forEach(([day, { start, end }]) => {
    if(start === '00:00 AM' && end === '00:00 AM') { return; }

    const ohString = `${start} - ${end}`;

    // Default to an empty list if this is the first time we see these office hours
    if(!officeHourDays[ohString]) { officeHourDays[ohString] = []; }

    officeHourDays[ohString].push(day);
  });

  // We now have an object { hourString: [days] }, we need to transform
  // it to the output string
  let officeHoursText = Object
    .entries(officeHourDays)
    .map(([hours, days]) => {
      const dayString = days.join(', ');
      return `${dayString}: ${hours}`;
    })
    .join('\n');

  // Loop over all possible combinations of subsequent days
  // (and what they should be replaced with), from longest
  // to shortest (best to worst match)
  const daysOfTheWeek = Object.keys(officeHours);
  // length - 1 because we don't care about sequences of 2 days or less
  for(let start = 0; start < daysOfTheWeek.length - 1; start  ) {
    for(let end = daysOfTheWeek.length - 1; end > start   1; end--) {
      // Friday, Saturday, Sunday
      const originalString = daysOfTheWeek.slice(start, end   1).join(', ');
      
      // Friday - Sunday
      const shortString = `${daysOfTheWeek[start]} - ${daysOfTheWeek[end]}`;
      officeHoursText = officeHoursText.replace(originalString, shortString);
    }
  }

  console.log(officeHoursText);
}
<button onclick='parseHours({"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}})'>Monday - Friday: 08:00 AM - 21:00 AM<br/>Saturday 08:00 AM - 18:00 PM</button>
<br/>
<button onclick='parseHours({"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"}})'>Monday - Wednesday: 08:00 AM - 21:00 AM</button>
<br/>
<button onclick='parseHours({"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"18:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}})'>Monday, Tuesday, Thursday, Friday: 08:00 AM - 21:00 AM<br/>Wednesday, Saturday 08:00 AM - 18:00 PM</button>
<br/>
<button onclick='parseHours({"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"18:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}})'>Monday - Wednesday, Friday: 08:00 AM - 21:00 AM<br/>Thursday, Saturday 08:00 AM - 18:00 PM</button>

CodePudding user response:

Here is a fairly concise solution that groups based on the previous period and if a day deviates it creates a new one.

const json_office_hours = '{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"10:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}';
const office_hours = JSON.parse(json_office_hours);

let periods = [], p;
for (const [day, { start, end }] of Object.entries(office_hours)) {
  if (start === '00:00 AM' || end === '00:00 AM') continue;

  if (!p || p.start !== start || p.end !== end) {
    p = { start, end, d_start: day };
    periods.push(p);
  } else {
    p.d_end = day;
  }
}

for (const { d_start, d_end, start, end } of periods) {
  const out = `${d_start}${d_end ? ` - ${d_end}` : ''}: ${start} - ${end}`
  console.log(out)
}

CodePudding user response:

const json_office_hours = '{"Monday":{"start":"08:00 AM","end":"21:00 PM"},"Tuesday":{"start":"08:00 AM","end":"21:00 PM"},"Wednesday":{"start":"08:00 AM","end":"21:00 PM"},"Thursday":{"start":"08:00 AM","end":"21:00 PM"},"Friday":{"start":"08:00 AM","end":"21:00 PM"},"Saturday":{"start":"08:00 AM","end":"18:00 PM"},"Sunday":{"start":"00:00 AM","end":"00:00 AM"}}';

let office_hours = JSON.parse(json_office_hours);


let office_days = [];
for (value in office_hours){
    office_days.push(value   " "   office_hours[value].start  " "   office_hours[value].end)
    console.log(office_hours[value].start)
}


console.log(office_days)
  • Related