Forum Academy Marketplace Showcase Pricing Features

Parallels: Date and Date Range Transformer (Now with Video Demos! 🎉)

Coming soon: Another cool-ass plugin from the person that brought you List Shifter and Calendar Grid Pro (that’s me). Here’s a preview:

The app I’m showing in the intro:

The boring text version of what Parallels can do:

Generate and transform dates and date ranges like a boss.

Parallels is the awesome date and date range transformer that solves a wide variety of problems when dealing with dates in Bubble. It’s a bit like List Shifter, but focused on date manipulations.

At its core, Parallels enables the easy creation of “parallel dates”, allowing you to turn any Bubble date picker (or date range picker) into a timezone-aware datepicker. Easily transform dates from one timezone into their “parallels” in different timezones.

But wait… there’s more:

Various actions allow you to easily create (generate or construct) and transform (modify or change) lists of dates and lists of date ranges (not to mention scalar dates and date ranges). Applications include date range sorting (by starts, ends or even durations), generating lists of calendar dates (and rewind/advancing by arbitrary amounts of time) , generating date ranges that represent “time slots” (and blocking based on conflicting dates or date ranges), shifting date ranges backward/forward in time, constructing lists of date ranges from lists of start and end dates, “splitting” a date range or duration into smaller component ranges, and much more.

Parallels gives you the tools to create and evaluate date range lists for applications including “book a time with me”, reservation booking, time range selection, etc. The same core date manipulation features pioneered in Calendar Grid Pro are made available by Parallels.

An innovative auxiliary outputs system gives you tons of built-in states for evaluating and storing date expressions, date list expressions, date range expressions, date range list expressions, etc. (5 Aux Outputs each with a date, list of dates, date range, list of date ranges, and text label fields.)

Parallels also offers locale-aware date formatting and locale-aware date date generation. Parallels generates local-aware day and month names so your creations are internationally friendly.

In the first release, Parallels includes a client-side plugin element (Parallels) as well as a server-side (backend) plugin for parallel date construction (SS Parallel Date).

As with all of my plugins (both free and paid), user demand will drive new features. Your feature requests are welcome here in the official support thread!

Parallels uses the powerful and lightweight Luxon date/time library to do some of its magic. Pages on which you place a Parallels element will load the Luxon library (currently version 1.26). This library is lean, mean and substantially smaller than moment.js (used, for example, in Calendar Grid Pro).

See you again soon,

OK, let’s get going with some videos about Parallels!

  1. History, inspiration and broad overview of Parallels capabilities:
    Loom | Free Screen & Video Recording Software

  2. The basics of the Parallels element main interface:
    Loom | Free Screen & Video Recording Software


Very useful! :+1:t2:

Looking forward to it @keith.

1 Like

Hi @keith,
Based on what I have seen so far of your plugins, I know this one is going to be AWESOME so wanted to be the first customer of your latest invention. Look forward to your videos so I can actually make it work! Glad to see that you are wearing a mask! Cheers

1 Like

Great stuff @keith :slight_smile:

1 Like

@kevin.hunt, thanks for your support! I didn’t realize one could actually subscribe/purchase Parallels yet… Thanks for being Parallels user #1!

(I made a bonehead error on initially submitting it to Bubble for review and the demo URL field was empty, so I had to resubmit.)

Videos will start shortly, but in the meantime, you can drop a Parallels on your page and read the docs in the editing interface to see how to generate a “parallel date” or otherwise transform the Input Date and/or Input Date Range. (The transformed date or range appears at the “Parallel Date” / “Parallel Range” outputs.)

Another good first step is to drop a text element on your page and explore the info exposed at the outputs labeled “Info: “.

There are a bunch of additional Actions that can be fired at Parallels to do the really fancy stuff.

Parallels generates Events when various Actions are complete. Most importantly, it generates an Event called “Initialized/Updated” when it is first initialized (and any time it updates because the inputs to the main interface changes). Use this event as your signal that Parallels is ready to accept Actions. (Like my other complex plugins, Parallels is generally not ready to accept Actions on Bubble’s “Page Load” event.)

Welp, I was meaning to record some documentation videos or Parallels today, but (1) as I was doing so, I got motivated to add a bunch of new features that make life cooler and easier and (2) OF COURSE, I ran into a very basic Bubble bug (relating to formatting dates), which sent me down an (unnecessary) debugging rabbit hole.

Anyway, here’s an interesting bug in Bubble:

I swear we’ll have some instructional videos about Parallels soon! (In the meantime, keep watching the plugins tab as I’m constantly adding new stuff still.)


Hi @keith ,

I am looking forward to learning all about your new Parallels Plug-In in the promised video but have been playing around with it and have some questions that you will hopefully answer in your video and/or respond to directly here.

If Not on Page Load……Right After?

I noticed that you made a point of saying that this and your other “complex” plug-ins cannot be used in an “On Page Load”. I don’t know why “On Page Load” would create complications but I am hoping that one can use Paralles and List Shifter in a workflow sparked right after page load. Is that possible and if is is, do you have any advice on how to spark the custom event (ie identify when page load is finished or trigger at some other time early after page load . Is there a finished page load flag I can tie it to?

Processing versus Display & Rendering

My interest in sparking a process right after Page Load, is driven in part by an assumption that may be wrong. It struck me that as custom states are held in memory in the browser (correct?) and that there should be some speed advantage once you’ve loaded the data into the custom state for faster load into and rendering of the display element. Am I totally off base on that?

If custom states do load faster in repeating groups (without leveraging any of the other amazing cleverness that you plugins offer (like intelligent pagination), I might take the upfront hit of a slower initial page load and do all my processing in the front end and get an immediate response rather than ask the user to wait for a response to a backend workflow. Trying to figure the trade offs……

Customizing to Match the Users Browsers “Capacity”

I am excited by the opportunity that several of your Plugins open up for leveraging the end users browser resources but am concerned that I might build something that is great for users with desktops and laptops that are beefy like the computers you have, but leave some users in the lurch in the process. Am I overthinking this?

If I am not, can you suggest any clever ways of estimating a browser’s horsepower? With certain apps, it might make sense to build an alternate version for folks with lower resources and redirect them to pages that are designed to be less demanding on user resources.

Other Plugins that Conflict with List Shifter and Parallels

I find it difficult to find my way back to specific conversations on the forum so hope that you can answer a question that I think you have already addressed elsewhere. I don’t want an exhaustive list of plugins that conflict with your front end tools but it would be great to know which of the more popular ones are going to cause problems. For example, I have considered using Sean Hoots’ version of Full Calendar and his AirDatePicker, and am already using Calendar Tool, Mishav’s Toolbox.

The Mysterious Disappearance of Sean Hoots

While we are on the topic of other plugins and a complete aside, I wanted to get your thoughts on the mysterious disappearance from the forum and apparent abandonment of all support for his plugins (I base this on uncontested comments in the forum and have been hesitant to adopt his plugins as a result) of Sean Hoots. I pegged you, Mishav, Cordurly and Sean Hoots as the top developers / smart guy contributors in the community so seeing Sean and Cordurly disappear makes me wonder if there was a reason.

@seanhoots – if you are listening – please chime in if I am off base on your reduced commitment to the platform. – if you are just ignoring customers who haven’t taken the time to figure out the obvious, please let me know!! Your plug-in looks awesome but unsupported plugins seem like a bad option

@mishav – many thanks for the awesome Toolbox plugin – I have only touched the surface with this wonderful add on but it has already proven to be hugely valuable!!

A talky introduction to Parallels! No demoing yet, but chatting through the available features:

(Sorry, these videos are recorded in 4K and so it seems Loom embeds don’t work here so you can’t just play the video in the page. I know you want to do that, but just click the durn link, eh? :slight_smile: )

Hey, some actual demoing of Parallels! This video covers the basic core features of the Parallels element itself:

Again, recorded in 4K, so click the link, yo!

Hey @kevin.hunt, addressed some of your questions in this video. Thanks for writing! I answer a few of your questions in this here video:

I’ll touch on some of your unanswered questions at a later time, but hopefully this addresses a lot of what you were asking about!

Hi @keith,
Thanks for the video!
Glad to hear that like the best diamonds your Plugins are conflict free.
And it is great to have my speed queries answered completely!
On that topic, is there any chance of you develop a week and day (ie time) view Calendar plugin. Your Calendar grid pro is amazingly fast but my requirements go beyond month views
Is developing such an app in your plans?
Please advise.

1 Like

Hi @kevin.hunt, well, Calendar Grid Pro does have a “time grid” mode that isn’t released yet. There’s an additional feature (a new way of displaying/selecting ranges) that’s kind of blocking deployment of that and so I haven’t committed to a date for either, but it’s something I work on every now and then. Now that Parallels is out, I’ll probably get back to that more seriously (once some more Parallels tutorial vids are out).

And in fact, Parallels is a way of creating a time selector (using the Split Range and Range List Check actions) which are the next things I should probably demonstrate!


Hi @keith,

I was able to get the split range function to develop a list of dates for me with no problems but am struggling to get the Range List Check Parallels function to work.

If I understand what this function is capable of doing, it would allow me to move a big chunk of what is currently an excruciatingly slow back-end recursive workflow and move it entirely into the browser. At the very least, it would allow me to filter a lot of the data and cut down the processing.

Can you give a bit of instruction on how to get this to work?

Hi @keith,
Range List Check Parallels checks for intersection. I need Bubbles “is contained by”. Do any of your other plugins have this? Calendar Grid Pro for example?
Please advise.

Hi @kevin.hunt,

I sent a very similar reply directly via email, but I wanted to note my answer here as well:

You can do exactly what you want with Range List Check, but there is one thing to know. The way that Bubble considers date ranges is (quite frankly) really dumb. Bubble’s range operators assume that the ranges are inclusive of both the start and end points. (That is, if I have a range that goes from 10 AM today to Noon today, Bubble’s :contains operator will return true for today at Noon.)

(The mathematical term for this is that the range is “fully closed”.)

This is, in fact, not how one should consider date ranges. A date range is much easier to work with if we consider the range to be “half open”. (That is the range is inclusive of the start point, but exclusive of the end point.)

This is much more natural, as, if you book an appointment for say, “10 AM today to Noon today”, you understand that your appointment begins at 10 AM but is entirely over at Noon. (That is, Noon is the start of the next appointment.)

And this is how Parallels understands date ranges in the Date Range Check action. (And, how it generates date ranges in the Split/Construct Ranges action.)

I’m sorry that I’m very behind on more videos about parallels, but will try to make one about these issues and the Split and Date Range Check actions (which are specifically for doing this sort of “what slots are available” computation) today.

Making this assumption about date ranges makes life much easier, but if we then need to Bubble’s range operators, we need to do a little extra logic to make them fit our paradigm for how ranges work. As an example, let’s look at range :contains point (this operator will return true if some range contains a certain date).

So let’s say we have some date range range and some date (point in time) date. And further (just like my examples above), range is the date range from 10 AM today to Noon today. And date is the date “Noon today”. The following expression will return true in Bubble:

range :contains point date

… because Bubble considers Noon today to be part of the range. But this isn’t how we would consider it. We would say that Noon is not part of range. And so, to get the behavior we want, we would write this expression as:

range :contains point date AND range's end is not date

And now this expression will return false, because the end point of range is date.

But this sort of logical adjustment is much easier to make than to construct our date ranges in the way that Bubble would have us do. For example, in Bubble-world, to make a date range that represents an appointment that goes from 10 AM today and ends at the very moment before Noon, we’d have to construct a range that’s like:

10 AM today ← range → (Noon today minus one millisecond)

Which, in Bubble, we can only construct as:

Noon today +(seconds): -0.001 ← range → 10 AM today

That is, we must take what we desire to be our end point, subtract 1 millisecond from it and then range that with our start point. This is abjectly stupid, of course.

Best Regards,

1 Like

Hi @keith

I might be wrong but I am pretty sure that Range List Check does not do what I need.
According to what is written in the documentation and based on what I have seen in results from testing, it looks for intersect.

Contains isn’t the opposite of Intersects is it? The nature of availability slots is that they leave a huge amount of the calendar empty which will generate zero intersections but no positive availability.

I am also interested in the performance boost that doing all of this in Processor would potentially offer. I was blown away by your video on processing speeds and they way that it can scale!!

@Boston85719 appears to have built something that looks a lot like what I want to build but has used Listshifter. TBR: Meeting Scheduler - Google Calendar Offline Access - Available Time Slots

I am hoping that he will fill me in on the details of how exactly he built it but if you have a minute to reflect on whether it could be built using Processor or nested Listshifter Iterates (assuming that those are technically possible) that would be awesome.



Nah, Parallels is going to be so much faster and easier. Are you just trying to do a “book time with me” sort of thing? Let me know a bit more about what you’re trying to build and I can customize my demo a bit for you!

1 Like

There are several routines that I am looking to build.

1.) a person looking to book a series of meetings (recurring events) and needs either on his own calendar or one someone elses. The proposed list of dates are compared with availabilities slots which are the same type of custom data type which of course have data range fields.

The tentative dates would be created as custom states and processed and then compared. ( ie a list of date ranges would be constructed, filtered for the repeating days e.g Mon, Wed, Fri and then compared to pre-defined available date that eventually will bisected by the confirmed meeting.

If there is a way to tag the information to the custom state so that different types of conflict are flagged (ie conflicts with persons personal google calendar but not with system). If that is not possible and there si a way to speed up actually creating a large list of custom data type records and filtering and tagging them, then I would prefer to do it that way - but I expect it will be a tricky trade off at best or so slow as to be untenable at worst.

Once the filtered and available confirmed dates are demonstrated, the person building the meeting dates will be able to review the conflicts (coming from two different calendars - google and system), remove or change some dates and add others and then confirm.

Once confirmed, the resulting custom states dates range list will be used to build a custom data type for those meetings/sessions that have the date ranges and a bunch of other data. If the actual creation of raw custom data record (ie one record for all the prefilted and availality checked data range) could be done more quickly than I would do the filtereing and availability checking after as it would allow me to capture additional data from the workflow to both Tentative record and Availablity that could be useful later.

I also thought using fields in the custom data type to capture datat that would allow me to use a two passes approach, one for start date and another for end date - to make a rather a cludgy and cumbersome manual “contained by”.

Another scenario would be to search for existing classes in a range of times when a student says they could do a class. That would look through a database of hundreds of classes to look for classes within that time range that had open slots. That would probably be too much data to make processing the data in the front end (or would it???) but there may be cases where there is a smaller subset of potential classes that could be filtered and loaded in the front end. How would you estimate that breakpoint?

I also want to be able to ask people to provide a range of times that are available, then filter the person with the predefined availabilities so that he can quickly pick the meeting times that leave the least amount of orphaned time slots.

Basically there are all stories with the same theme.

I don’t see how Parallels Range List Check could work for any of these- but that could be because I have have availability ranges defined a different way than you do. Take for example a tutor that has no availability in the morning. Any attempts to book a session that begins and end in the morning will result in a zero intersection - which parallels considers a good range.

Thanks in advance for the help!!



So, real quick: don’t get spun by the output of Range List Check.

What this action does is test some list of date ranges against some other lists of date ranges and/or points-in-time (dates).

The ASSUMPTION (Parallels makes) is that your list of date ranges and/or dates to test against represent UNAVAILABLE times.

The reason that this is the default is that time is infinite (for all intents and purposes). So the list of AVAILABLE dates is infinite and the list of UNAVAILABLE dates must be finite.

But Parallels returns to you all of the data you need to do things the opposite way.

You have some (finite) list of time slots. And then, of those slots, we return to you the list of slots (the “good” list) that would be available if the test list represents unavailable times.

And then we also return to you the list of “bad” slots (which is just the full list minus the the “good” list). These must be the slots that are NOT available.

Now, what if our test list represents slots that are AVAILABILE? Well, the “good” list is then just those slots that are NOT available. And our “bad” list is the list is the list of slots that ARE available.

As the programmer, you can decide what these things mean. But I have to label them as something so that you can take the appropriate action.


Thanks for the explanation.

I actually originally set out developing non available data ranges but was convinced that the opposite approach made sense … of course that was before I had experienced the unacceptable processing times of the back end workflows.

One thing that I really like about the “contained by” with Availability dataranges approach as opposed to the one using Unvailable data ranges, is that you are able to record each time there is a tentative request for a specific available time slot - this of course assumes that you can record that data on customer data type or in some array that could be used to tie back to or create a custom data record.

I have the impression that Processor would let me do (ie build an array with more than just an index process a custom data type) that AND that processor had the contained by function. Just getting confirmation one way or the other on these capabilities would be huge.

The reason that this approach is interesting, is that you can start to analyze the demand for that specific slot. Using the negative image of the availability slots - ie unavailable and "does not intersect " would not allow me to do this, would it?

What your proposing is clearly a better solution than relying on backend workflows but not quite as elegant or data rich as I had been hoping for. So I am clearly delighted. But I am also greedy!! :slight_smile:

Parallels is definitely a high value option. The question remains, can I get everything I want with Processor? I have had no luck figuring out how to work Processor beyond the simple example you have in one of your videos but I have the impression that it would allow me to do what I want with two different scenarios.

1.) Build all tentative dates as custom states and process them AND capture some data about which dates tie to which availability dates (I am unclear whether the arrays in Processor are simple index and single data or if more complex arrays are possible - if they are the resulting list could be used to create new custom data types at the end of the process after the user has reviewed the outcome and pressed confirm booking

2.) Use Parallels/Listshifter to do some of the heavy lifting to cut down the creation of the custom data types for the sesions that are the fields that tie to those the tentative dates.
Then process those custom data types in Processor and use fields in that Custom data type to capture data like which Availability slot corresponds to which tentative request for booking. the output list could be used to update the original custom data type record.

Could I do any of these two with Processor? I may end up liking the Parallels approach best because it is elegantly simple to use the way you have it set up AND lightening fast. But I would love to understand whether those use cases for Processor would work as well. Just getting a clear example of what can and cannot be done with Processor would be huge. Not knowing the plugins limitations is frankly driving me crazy.

Thanks in advance for your response.