How To Schedule API Workflows Based On A Date In A Different Timezone Than Current Users Timezone

I’m trying to schedule an api workflow on a specific date/time at a different location than the current user’s location.

Bubble accepts current date/time based on current users time zone but i need it to be in the timezone of the Thing i’m trying to manipulate.

I have the timezone ID of the Thing i’m trying to manipulate but can’t “set” the api workflow schedule based on that date because when I use the ‘formatted as…’ and select the timezone it changes the type to TEXT which can no longer be used…

Bump… Any ideas on this guys? STUCK!

Use moment and moment-timezone. I’m currently building an awesome explainer app for this, in response to your question…

It’s just taking a little time (pun likely intended).

3 Likes

Hi @JustinC,

See if this is helpful to you. This is a perhaps much better explanation of the technique I’ve previously described her (An "Easy" Way to Convert Bubble Date/Times to the Same Date, but in a Different Timezone):

Timezoner: An Explainer App for Timezones - Run Mode

Timezoner: Edit mode (anyone can view):

Hope this helps,
Keith

3 Likes

This is an excellent piece.

I’ve gone through it a number of times now and can’t seem to understand how I’m supposed to schedule an API workflow based on the time in another jurisdiction.

Each time i try and ‘format as…’ and select the timezone ID the issue checker turns red:

image

My data has the timezone ID saved already and I’m trying to manipulate a date based on the timezone ID of the Thing itself.

It seems that the example app has more to do with output of the date/display of the date on the page itself and I also couldn’t find any toolbox plugin actions in the editor so that I can see if a new date was ‘saved’ to the database in the example. - is this possible?

Maybe adding the ability to save a date/add 1 hour to a date saved in a different time zone may be helpful too!

Hi Justin,

I think what you wanted to know was “How does one create what Keith calls a parallel date”? You can do it with Run Javascript or in an expression. That’s the “green” section of Timezoner:

The technique here is as follows:

  1. Snag a date object (like, from a datepicker as in the sample app) that is from any timezone. Like let’s say that date is “Noon today in America/Los Angeles”.

  2. But I don’t WANT that date. Let’s say that the date I WANT is “Noon today in America/New York.” The original date object, “Noon today in America/Los Angeles” is “3 PM today in America/York”. That’s not what I want.

  3. How do I get from “Noon today in Timezone 1” to “Noon today in Timezone 2”? (You and I happen to know that today, New York is three hours ahead of Los Angeles. But what if this date is sometime in the past or sometime in the future where we have no idea what time standard is being observed and, further, Timezone 1 and Timezone 2 are completely arbitrary and we cannot know them ahead of time – i.e., they are dynamic.)

  4. That’s what Expression: Parallel Date does.

  5. Expression: Parallel Date’s value is a new date object representing the the same “day and time” parameters, but actually in the target timezone.

  6. Codewise, it works like this:

    var target_zone = “the Timezone ID string of our target zone” // like “America/New York”

    var date_string = “a string representation of the date we want to transform” // a bubble date formatted as yyyy-mm-dd HH:MM:ss.L in the original timezone

    moment.tz(date_string, target_zone).toDate(); // construct the parallel date in the target zone

That’s it. (Inspect the Conditional tab of Expression: Parallel Date for how you build it.) Obviously, you could collapse this into a single line of code, but it gets hard to understand.

Now that you have that date (Expression: Parallel Date’s value), you can use it wherever we need a date! Like, we can set some field of type date to Expressioin: Parallel Date’s value.

Or, we can pass it to the Scheduled date field of Schedule API Workflow. That field expects a DATE, not a TEXT. You are getting red warning because you are sending a text to a date field. You send a date. You do not FORMAT the date (formatting the date returns a text).

Again, we used an Expression element here, but we could use a JavaScript to Bubble element and a Run JavaScript action. In that case, the pseudocode in the Run JavaScript would become:

var target_zone = "the Timezone ID string of our target zone" // like "America/New York"

var date_string = "a string representation of the date we want to transform" // a bubble date formatted as  yyyy-mm-dd HH:MM:ss.L in the original timezone

var newDate = moment.tz(date_string, target_zone).toDate();

bubble_fn_whatever(newDate);

Our JavaScript to Bubble element should be configured as date type and to return a value and, in the example above I called its function name “whatever”. (JS to Bubble elements create a function that we can call to send the element an object. “bubble_fn_whatever(newDate)” passes date object newDate to the JS to Bubble element whose function is named “whatever”.

2 Likes

I know this sounds a bit complicated. That’s because it is complicated. But moment/moment-timezone makes this easy.

Without moment-timezone, you get stuck in a hell of “figure out date 1’s offset from UTC”, “figure out the target timezone’s offset from UTC”… “oh wait, we know the offsets right now… but we don’t know the actual offsets on that particular day and have no way to figure them out”… “Oh crap maybe we’ll just wing it and say that an hour off here or there isn’t a big deal”…

But if you really want to confidently do these types of conversions, this is how you do it.

1 Like

Getting this now thank you!

What tool or plugin do I use to create an action that runs this in the background?

Toolbox plugin? I see that you indicate JavaScript to Bubble - what plugin does that and will allow me to access the newly created date object in an action and save it as a scheduled API workflow start date/time?

And do I still need to paste the moment scripts anywhere if I’m accessing and computing things in the back end as an action?

(Forgive my ignorance, never done this before!)

It would cure all my headache if the example app could be added too and with some actions that save the date in the database:

  1. A flight/train/bus ticket booking date that’s saved from one timezone (current users timezone), but the departure location/airport/terminal is in a different timezone than current user.

  2. Save that date with the timezone ID of the departure location/airport/terminal to be manipulated later.

  3. Allow user 2 (a travel agent, for example) to change the original date in the target timezone of the terminal/airport/train station by adding 2 hours to the original departure date/time, and re-save it as a date object which could then be later ‘formatted as…’ whatever you want to display to the users (as text).

Have you examined this project in edit mode?

Yes, Toolbox is the source of these elements (see plugins tab in editor)!

As for loading scripts: yes you must do that as, at present, there is no way to run libraries server-side. This date construction is all happening in the page.

1 Like

One question I have is whether this will also transform the date and create a parallel date through an API workflow that gets triggered by the user?

Because how can I place the scrips onto the page and have them run is my concern…

I do have:

  • Current time/date of workflow user (i assume bubble provides this or is the server time or something)
  • Target time/date based on address value + time zone ID

Additionally - something broke on the example all of the sudden:

Yeah, on that error: For whatever reason, the Expressions are firing before moment/moment-timezone is fully loaded. (This is hard to control in Hobby as you can’t put the script calls where they should really go – see the comments in the HTML element.) I can fix this (and that in itself is instructive – basically one has to run some script to check for moment/moment-timezone libs being loaded and THEN let the Expression elements run), but I’m surprised it suddenly changed behavior. #shrug

(The lesson is that the “Page is loaded” state and even “Page is loaded (entire)” state can be reached before required libraries are fully loaded. This doesn’t come up real often, but moment-timezone-plus-data is rather large.)

Anyway, everything you need to understand this is pretty much there in the edit mode (there’s LOTS of comments in the code for the Expression elements).

As for in an API workflow – NO. As I said, this is all client-side right now. So yeah you have to do it in the page. But of course, you can pass Expression: Parallel Date’s value to a Schedule API Workflow call as the scheduled time. (Which is what you want anyway, right?)

If you wanted to do this entirely server-side (zero user interaction) – like say you have an API Workflow that runs periodically and wants to do these types of transformations – you’d have to set up a little microservice/API of your own to run that code. (Webtask.io makes this pretty easy. I should do a video tut on that sometime.)

At some point (hopefully soon), one will be able to install NPM packages for server-side plugins and then it’d be possible to build a moment/moment-timezone server-side plugin but that’s not something that can be done.

Anyway, examine the edit mode version of the project and play around with this idea in your own project. I’m sure you could figure out a way to make it work.

1 Like

That would be greatly appreciated Keith

2 Likes

Hey @JustinC: To absolutely positively fix the issue of scripts not being loaded before the Expressions call them, I added an On Page Load workflow that does some Run JavaScript / JavaScript to Bubble element magic. It’s well documented in the “notes” on that workflow.

This is how I do this in my vacation rental booking widget. That thing is a complex reusable and it turns out there’s just no “passive” way to ensure that the scripts are loaded before we try to use moment/moment-timezone, so I do this check on page load and then set a JS to Bubble element’s value, which is used in a condition on Expressions that need those functions.

Yeah… and I guess doing something with moment.tz wouldn’t be a bad example.

But hey, if you want a REAL FAST and REAL SIMPLE example (and it really is this easy), check out this Auth0 blog post (I’d never seen this page before even though it’s old-ish):

https://auth0.com/blog/auth0-webtasks-the-quickest-of-all-quick-starts/

Oh, @JustinC: BTW, keep in mind that, while to do this the “easy” way requires you to do it in the page, our “target timezone” does not have to come from user input. It could be the results of a search or Some Thing’s Geographic Location’s Timezone ID, right?

So, it’s not like the user has to know what we are doing here, but we do need to get the target zone ID down to the browser.

@keith

Got the same issue as Justin now. My API Workflow time (based on Bubble server time pacific) do not correspond to the user time. So when I ran a specific API Workflow, Bubble server doesn’t know about it… and just apply local Bubble time server to any dates.

Now, I understand that I have to record timezone for each user (or contacts) and need to make some conversion based on Bubble location server (like +3 hours for New York). The day Bubble change the server for another location… we are in trouble. So I expect that and make an admin value Bubble_Server_UTC = +3… So the day it changed or the day I have a dedicated server in China, I simply change the value.

Any solution I’m not aware of with ‘Bubble dates’ that I can on the spot change the date value for a specific timezone on an API call Schedule?

edit: A work around is to create an initial date, and never touch the ‘current time’ function (so it’s always based on the user timezone).

This topic was automatically closed after 70 days. New replies are no longer allowed.