skip to Main Content

I have a function that receives an hours array (hoursArray) and a number variable (minutes).
hoursArray are the available hours of a barber schedule. Duration is de duration of the service that the client books (hair salon).

The current code returns another array with the hours of the hoursArray that are available according to the variable ‘minutes’, that is to say: If the array hoursArray is:

const hoursArray = [
    "09:00",
    "11:00",
    "11:30",
    "12:00",
    "13:00",
    "14:00",
    "14:30",
    "15:00",
    "15:30",
    "16:00",
];

And minutes is: minutes = 30

The function returns:

[ '09:00', '11:00', '11:30', '12:00', '13:00', '14:00', '14:30', '15:00', '15:30', '16:00' ]

Why?

The arrayHours in this case are intervals of 30 minutes. If the arrayHours starts with 09:00, 11:00 it means that 09:30, 10:00 and 10:30 are already reserved. So in the return array, this hours don’t appear, only 09:00 and 11:00. This is the logic for all of the array.

If minutes = 60 with the same hoursArray, the function returns:

[ '11:00', '11:30', '14:00', '14:30', '15:00', '15:30' ]

The code that models this is:

function getAvailableHours(hours: string[], minutes: number): string[] {
    const availableHours: string[] = [];

    for (let i = 0; i < hours.length - 1; i++) {
        const currentHour = hours[i];
        const nextHour = hours[i + 1];

        const [hour1, minute1] = currentHour.split(":").map(Number);
        const [hour2, minute2] = nextHour.split(":").map(Number);

        const totalMinutes1 = hour1 * 60 + minute1;
        const totalMinutes2 = hour2 * 60 + minute2;
        const timeDifference = totalMinutes2 - totalMinutes1;

        if (minutes === 60) {
            if (timeDifference >= minutes) { } else {
                availableHours.push(currentHour);
            }
        }

        if (minutes === 30) {
            availableHours.push(currentHour);
        }
    }

    if (minutes === 30) {
        availableHours.push(hours[hours.length - 1]);
    }
    return availableHours;
}

But now, I need other functionality, I need that the function to do the same but with more values in the ‘minutes’ variable (15mins, 30mins, 45min or 60mins)

Other cases of use:

const hoursArray = [
    "09:00",
    "09:30",
    "10:30",
    "11:00",
    "11:30",
    "12:00",
    "13:00",
    "14:00",
    "14:30",
    "15:00",
    "15:30",
    "16:00",
];

minutes = 60

Result:

[ '09:00', '10:30', '11:00', '11:30', '14:00', '14:30', '15:00', '15:30' ]

Why?

if minutes are 60 is why for this service we need 60 mins. This means that 09:00 is showed in the return because hoursArray have: 09:00, 09:30 and 10:00, since hoursArray are intervals of 30 mins we know that from 09:30 we have 60 minutes ahead. In the caso of 09:30 you can notice that in doesn’t appear in the return, because we don’t have 60 minutes ahead 09:30

Other case:

 minutes = 30

Result:

[ '09:00', '09:30', '10:30', '11:00', '11:30', '12:00', '13:00', '14:00', '14:30', '15:00', '15:30', '16:00' ]

If you copy the code and execute it in your IDE, you can make tests with other cases with other hours in hoursArray and changing between 60 and 30 on the ‘minutes’ variable in order to better see the operation.

I need that the function allows to return an array but also with minutes = 45 and minutes = 60, because currently it doesn’t work with this values.

Here there is an example that how should be the results and the input data:

In the new version of this function, the hours in hoursArray must be intervals of 15 minutes, like:

hoursArray = ["09:00","09:15","09:30","10:00","10:30","10:45","11:00","11:15","11:45","12:15","12:30"]

If one hour doesn’t appear is because these 15 mins are booked. In this case for example "10:15" is not available this is because someone has booked one service of 15 minutes at 10:15.

With this hoursArray and for example duration = 45 mins the result should be:

["09:00", "10:30", "10:45"]

But, on the ohter hand, if duration = 15, the array should be the same that hoursArray.
If duration = 30 the availableHours should be:

["09:00", "09:15", "10:30", "10:45", "11:00", "12:15"]

In this case, for example 09:15 are available because we have free 30 mins ahead: the next hour is 09:30 and we have intervals of 15 mins so we have free from 09:15 to 09:45. I hope that this explanation helps.

I’ve been trying for months but I can’t get a good result.

2

Answers


  1. Okay, it appears that you first need two functions to convert between the "human-readable" time representation and the number of minutes:

     // timeToMins('09:30') -> 570
     function timeToMins(time: string): number { ... }
     // minsToTime(570) -> '9:30'
     function minsToTime(mins: number): string { ... }
    

    Now, assuming your input is a list of start times for already booked time slots with a certain duration, you can compute a list of available slots with something like this:

      let bookedMins = input.map(timeToMins)
      let availMins = []
    
      for (
            let mins = timeToMins(OPEN_TIME); 
            mins < timeToMins(CLOSE_TIME);
            mins += duration
      )
         if (!bookedMins.includes(mins))
              availMins.push(mins)
    
      return availMins.map(minsToTime)
    

    where OPEN/CLOSE_TIME are string constants and duration is the slot duration in minutes.

    Login or Signup to reply.
  2. You could benefit from iterating the input array in reverse, so that you can track which is the upcoming slot that is not free.

    Also, since you want to work now with blocks of 15 minutes instead of 30, I’d suggest to define this information as an extra parameter to your function. Let’s call it unit.

    Below is a possible implementation. The driver code defines all your examples as test cases and then executes and verifies them:

    function getAvailableHours(hours, unit, duration) {
        let occupied;
        return hours.toReversed()
             .map((s, rev) => [s, s.split(":").reduce((h, m) => h * 60 + +m)])
             .filter(([, m], i, rev) => {
                if (rev[i-1]?.[1] !== m + unit) occupied = m + unit;
                return occupied >= m + duration;
             }).map(([s]) => s)
             .reverse();
    }
    
    // Define test cases
    const tests = [{ 
        hours: ["09:00","11:00","11:30","12:00","13:00","14:00","14:30","15:00","15:30","16:00"],
        unit: 30,
        duration: 30,
        expected: ["09:00","11:00","11:30","12:00","13:00","14:00","14:30","15:00","15:30","16:00"]
    }, {
        hours: ["09:00","11:00","11:30","12:00","13:00","14:00","14:30","15:00","15:30","16:00"], 
        unit: 30,
        duration: 60,
        expected: ["11:00","11:30","14:00","14:30","15:00","15:30"]
    }, {
        hours: ["09:00","09:30","10:30","11:00","11:30","12:00","13:00","14:00","14:30","15:00","15:30","16:00"], 
        unit: 30,
        duration: 60,
        expected: [ '09:00', '10:30', '11:00', '11:30', '14:00', '14:30', '15:00', '15:30' ]
    }, {
        hours: ["09:00","09:30","10:30","11:00","11:30","12:00","13:00","14:00","14:30","15:00","15:30","16:00"], 
        unit: 30,
        duration: 30,
        expected: [ '09:00', '09:30', '10:30', '11:00', '11:30', '12:00', '13:00', '14:00', '14:30', '15:00', '15:30', '16:00' ]
    }, {
        hours: ["09:00","09:15","09:30","10:00","10:30","10:45","11:00","11:15","11:45","12:15","12:30"],
        unit: 15, // !!
        duration: 45,
        expected: ["09:00","10:30","10:45"]
    }, {
        hours: ["09:00","09:15","09:30","10:00","10:30","10:45","11:00","11:15","11:45","12:15","12:30"],
        unit: 15,
        duration: 15,
        expected: ["09:00","09:15","09:30","10:00","10:30","10:45","11:00","11:15","11:45","12:15","12:30"]
    }, {
        hours: ["09:00","09:15","09:30","10:00","10:30","10:45","11:00","11:15","11:45","12:15","12:30"],
        unit: 15,
        duration: 30,
        expected: ["09:00","09:15","10:30","10:45","11:00","12:15"]
    }];
    
    // Execute test cases
    for (const {hours, unit, duration, expected} of tests) {
        const res = getAvailableHours(hours, unit, duration);
        console.log("------------------------------------------");
        console.log("hours:", ...hours);
        console.log("unit:", unit, "  duration:", duration);
        console.log("result:", ...res);
        if (JSON.stringify(res) !== JSON.stringify(expected)) {
            throw "Expected " + JSON.stringify(expected);
        }
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search