📆 Working with dates in calculation fields

Let’s be honest - date and time are crucial elements of our daily work and uses cases, but can be a huge pain when building - and let’s not forget time zones :exploding_head:

We composed this guide based on frequently asked questions and our own experience in building real world scenarios that require date and time usage in calculation fields.

With Tape offering full third party library support, one of the essential date libraries are date_fns (docs) and moment (docs), where the former is mostly present for historical reasons. Due to various reasons our guides focus on using date_fns. For more details on libraries available, check the developer docs.


Preliminaries

It is worth noting that all dates that contain a time in Tape are stored without timezone in UTC, and displayed to the user in their local time zone (the browser assist with that). When selecting a date and time, the user provides an exact point in time that will be persisted as its UTC representation inside the database.

Date field values without a time will be stored as a calendar day, which has no time zone either. If you refer to a calendar day, e.g. the 12th Oct 2023, you would refer to that day, while obviously the exact start and end point in time depend on timezone. Think about naming your birthday or an anniversary.
That is why in contrary to above, calendar days will always be displayed as the same day to any user in Tape.

Note, that calculation fields are executed inside the Tape backend which runs in UTC for convenience and neutrality reasons. While this is irrelevant in many cases, it may lead to some challenges when time zones are relevant. Some of the examples will dive into those situations.


Library usage

Using the global date_fns variable, you have access to basically all functionality the library has to offer. Refer to the docs for all functions and capabilities:

Many of the following examples make use of some of those functions to derive or calculate new dates.


Examples

This is a list of script examples to achieve various things using dates. Note that [@Date with time] will refer to your date token, you do not need to add the [ and ] characters. Your script would then look something like this:

For simplicity the examples are provided as code snippets and not as screenshots. You can simply copy the code and replace [@Date with time] with your field token by typing the @ character in the editor as you’re used to.

Extracting a date’s calendar year

date_fns.format([@Date with time], 'y')

Displaying a long date

date_fns.format([@Date with time], 'PPPP')

Note: You may recognize a pattern here. The second paramter 'y' / 'PPPP' is the format string. There are many available, check the docs for more info.

Adding n days to a date

date_fns.addDays([@Date with time], 3)

Adding n months to a date

date_fns.addMonths([@Date with time], 5)

Displaying a date’s weekday name

date_fns.format([@Date with time], 'EEEE') // a date field value, e.g. yields "Thursday" 

date_fns.format(new Date(), 'EEEE') // today, e.g. yields "Thursday" 

Calculating the end of the day

const utc = date_fns_tz.utcToZonedTime([@Date with time], 'Europe/Amsterdam')
const endOfDayUTC = date_fns.endOfDay(utc)

// yield result
date_fns_tz.zonedTimeToUtc(endOfDayUTC, 'Europe/Amsterdam')

Note: This example required more code, as we need to consider the timezone. The script takes the provided point in time, and utilized the desired timezone, in this case Europe/Amsterdam, to “go from there” and determine the end of day. We go back in the end to persist UTC again. This will work if you provide your respective time zone.


Date return type

Tape enables you to select the return type of your calculation fields. This will enable respective filters for that field, and also display data properly. For a number return type you can set the number representation (similar to pure number fields), and for date you have similar settings as for the date field at your disposal, such as including the time or not:

Note that the respective return type will only be available if your script returns proper data. For dates, that will need to be a JavaScript date instance.

Feel free to create one using date_fns parse:

date_fns.parse('2023-10-15 15:00Z')

Obviously, this should be the way to go when using above examples. You can then expose the result and fully leverage the powerful date filters. :partying_face: :

Shared example to get started :rocket:

Time to get your hands dirty. We created a little demo workspace that you can clone into your own Tape organization to get a head start and play around with the scripts.

Use this link and the regular “Duplicate” button on the top right to get started:

Date calculation examples share link


:eyes: And here’s a sneak peak of what you get:


Feedback

Anything missing here? Another use case that you would like to see, or that you struggle with? Drop us a comment and we’ll append it to the guide. :point_down:

6 Likes

FWIW - here on this conversation about using dates in calculation fields, I’d like to link to this previously submitted request: ⭐ Allow usage of date field end date in calculation fields

Calculating the difference between two timestamps is a common request we get from clients. While it can be done by using two separate date fields than a calculation (see [✅ Solution] Date delta in Calculation fields )
It would be so nice if we could get an option to put in a start date/time and an end date/time using a single date field and then call the start/end times separately in calculation fields.

5 Likes

@Tim is there a bug currently?

The calendar formatting for the related calculation field only works with “Minimum of” or “Maximum of”, not when directly accessing “ All of Erster Tag”.

Is that the way to go?

Not a bug… as this was an incoming relation, it could potentially hold more than one link. When adding direct access on the first element, it works.

image