I have an application displaying a week of bookable time slots (of a resource).
A time slot is always 30 min long and can either start :00 or :30.
The availabilites are internally represented by the week's minutes (in an array), 0
meaning the week's first minute at midnight and 10079
the week's last minute. This means that a resource with 100% availability have 10080 numbers in an array, 0 through 10079.
E.g. the following means that this week has 70 available minutes between 09:55-11:05 on the first day of the week:
[595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665]
How would I calculate and display any possible time slots (i.e. a minimum of 30 consecutive minutes)?
Given the data set above and the current week, and with Monday as first day of the week:
[Mon Aug 08 2016 10:00:00, Mon Aug 08 2016 10:30:00]
[Mon Aug 08 2016 10:30:00, Mon Aug 08 2016 11:00:00]
I don't know if this is easy or not, but I'm currently a bit clueless how to go about doing this in javascript? Any hints are much appreciated!
Here's a basic function which takes an interval length,
n
, and an array of numbers (which represent minutes of availability).By calling
getIntervals (30) (availableMinutes)
we'll get all available time slots …Note, the
range
procedure below is only used to create sample data. You do not need to include it in your program.Just make sure these minute markers are minute offsets of a UTC timestamp and everything will be easy. Displaying these minute markers is just a matter of adding
X
minutes to a UTC timestamp that is set to the beginning of a resource's week.We'll create a little procedure here called
timestampAddMinutes
which takes the minute number and converts it to a Date object based on the resource's timestamp,week
Then, we create a
getIntervalDates
procedure which applies that to eachfrom
andto
value of each interval in our arrayYou'll see that
from
andto
were each converted toDate
objects. Also pay attention to how my browser (in EDT timezone) is automatically converting the UTC timestamp to be displayed in my current timezone. The output above will show them inTZ
string format, but they're fully usable Date objects. That means you can call any Date method on them to get specific details like day of week, hour, or minute, etc.And since our
getIntervals
function is working properly, you'll also see that each interval is 30-minutes long and starts on:00
or:30
Output
The power of a single parameter
Just to show the the flexibility of
getIntervals
, here's what it would look like if you changed a resource's interval length to 75 minutes (instead of 30).Output — each interval is 75 minutes long and starts on a starts on a 75-minute interval marker
Alternative Implementation
If you have to put comments in your code, you're probably doing something wrong. So I've broken one of my own rules by heavily relying on comments to make intent clear in the above implementation.
This implementation instead uses tiny procedures which each have immediately apparent intent. Moreover, I used a
switch
statement which allows us to logically group some of the loop responses without having giganticif
conditions.Now you can see that the loop only responds in one of 3 ways.
count
and updatesprev
to the current minutemake
) toacc
and does acount
resetdefault
case, it incrementscount
and updatesprev
Furthermore, now that the procedures have been broken down into tiny pieces, you can see how some of them could be easily reused in other areas of your application
And yep, it works the same. The idea here is if you're going to do the same thing more than once, why not define a procedure and use that instead ? By no means do you have to do go this far, but you can see how generic tiny procedures do reduce the overall complexity of
getIntervals
.Now any time you want to check if two numbers are sequential, you have a procedure for that —
isSequential
. Same withisDivisibleBy
— you can easily check ify
is equally divisible byx
without duplicatingy % x === 0
everywhere it's needed in your app.And, believe it or not, even these little procedures I've given you here can be broken down into more parts
Bottom line is: don't go crazy with it; know when enough abstraction is enough for your particular problem. Just know that there is incredible techniques out there for abstracting complexity away. Learn the techniques and know when to apply them. You'll be happy you did ^_^