OK: A Quick Primer on Date Ranges
What is a date? You are probably familiar with the
date data type. A date describes a unique point in time.
(Remember: Whenever we are talking about “dates”, we are actually talking about date/time objects. When we casually say “date” we should always remember that what we are saying is “a date/time”.)
A date represents some point in time. A date may be before some other date (in which case it is “in the past” with respect to some other date and would be “less than” that other date). A date may be after some other date (in which case it is “in the future” with respect to some other date and it would be “greater than” that other date).
So, knowing what
dates are… what is the
date range data type? A
date range describes a unique time period.
These unique time periods are defined by a start date/time and an end date/time. The are constructed using the “<- range ->” operator possessed by objects of date type. You make one like this:
date_x <- range -> date_y
Doing this creates an object of date range type. The lesser of the two dates becomes the date range’s :start. The greater of the two dates becomes the date range’s :end. In a workflow, it might look like this:
^^^ Here we create a date range stored as a local variable (custom state). This date range goes from “now” (the time this workflow step runs) to “30 seconds from now”.
Here’s another one:
^^^ Here we create a date range that goes from “now” to “15 seconds from now”.
In the same way that various
date operations allow you to compare points in time,
date range operations allow you to compare time periods.
Do you need to know if some point in time is within some time period? (You want to know if date_x is within some start date/time and some end date/time.)
Do you need to know if some time period is within some other time period? Do you want to know if some time period overlaps with some other time period?
Well, date range operations can answer these (and other) questions.
Look at the examples above. You already know that the second time period (My Other Date Range) is within the first time period (My Date Range). But how would our app know?
The :contains Operator
The Reference, as you note, is incomplete (and sort of incorrect) about the various date range operators. The :contains operator is how we tell is one date range is fully enclosed by another date range.
My Date Range:contains My Other Date Range will be “yes” if My Other Date Range is entirely within My Date Range.
The :contains point Operator
The :contains point operator is missing from the reference. This operator is used to tell us if a single date (a single point in time) is within a date range (a time period).
Let us say we have a date object (a single point in time). We can understand if that date is within some date range using the
:contains point operator. My workflow above has a third step like this:
So now we could check if that date is inside of one of the previously constructed date ranges like this:
My Date Range:contains point Some Date will be “yes” if Some Date is after the start of My Date Range, but before the end of My Date Range. It will be “no” otherwise.
Let’s put this into practice. Here’s the page that executes the workflow action I’ve been describing. When the button here is clicked, it makes these date ranges and dates. Then a text element tells us about them:
The expressions which yield these results are shown here in edit mode:
Other Things We Could do With Date Ranges
There are of course other things we can do vis-a-vis time periods. Here are the other options. (And now the documentation about them should make more sense.)
Of these, “overlaps with” is one of the most useful. Suppose you have a date range that represents a haircut appointment for Albert with stylist Carlos. Now Betty wants to book an appointment with Carlos. Is Betty’s desired appointment available? (It IS NOT if Betty’s selected date range “overlaps with” Albert’s appointment date range.)
So there you go: That’s what date ranges are for.
Note: Date ranges do NOT have to be stored in the database or stored in a local variable (custom state) to be useful. We can usually construct a date range on the fly inside of any expression.
Let us say we have 4 date objects: datew, datex, datey and datez
Is datez between datex and datey? That’s:
datex<- range ->datey:contains point datez
Does the time period datew to datex overlap with time period datey to datez? That’s:
datew<- range ->datex:overlaps with datey<- range ->datez