# Solution for Adjusting Timezone / Date Picker / Server (UTC-GMT) Time Difficulties

Dear All,

## For those who don’t like reading, the key here is that MathJS Local calculates difference between text values: say 02 (as text) minus 01 (as text) gives 1 (as number).

Say, we pick 12th July in a Datepicker input while watching football in Moscow, and as a result we would see it as 12th July 00:00:00.

In London we would see this date as 11th July 22:00:00. i.e. -2 hours current time difference.

Wonderful Bubble server would record this date as 11th July 21:00:00 as Bubble seems to store dates in UTC format (by the way UTC is the same as GMT).

Say, we want to have all dates aligned to London time, which in the summer is UTC (GMT) + 1 hour.

The solution is to adjust what Bubble writes down after we pick a date [and time if you wish so].

To have 12th July 00:00:00 seen in London, we would need to pick 12th July 02:00:00 from Moscow.

To do this without determining Moscow’s timezone [which requires user’s permission to get their location], we would need to:

1. Calculate the difference in hours between Moscow (i.e. user’s current time, while we don’t know their location) and UTC, this would give us +3 hours;

2. Calculate the difference in hours between London (our preferred timezone) and UTC, this would give us +1 hours;

3. Calculate the difference in hours between the above two (this is to adjust to summer/winder time difference), the would give us (+3)-(+1)=(+2) hours (this is needed as, for example, in Moscow time doesn’t change for Summer and Winter, while London’s time does change, so we do need to account for that in each date calculation, i.e. we cannot just take current +2 hours difference and apply for all future adjustments);

4. Adjust date picked by the difference obtained in 3, so take 12th July 00:00:00 picked in the datepicker and add 2 hours.

How do we do the above with Bubble in a stable and reliable way?

By using MathJS Local plugin we are able to calculate differences between texts.
[!!! MathJS doesn’t seem to return number, so we can’t use the result to adjust date later, use MathJS Local]

• Equation below is our calculation, which would need to be performed twice to cover Steps 1 and 2 above:
(so “only Hours of Time in Users Current Timezone Format” minus “only Hours of Time in UTC Format”)
[do not worry, although “HH” is returned as text, MathJS does the calculation, in the first part of our calculation we need to have replacement for 00 to 24, also where the difference in less than -12 we would need to add 24 to account for date change between time zone]
[NB the minus sign is typed as text between two dynamic values]

• Below is how to get “only Hours of Time in Users Current Timezone Format” (in our case London):
(HH returns only hours)

• Below is how to get “only Hours of Time in UTC Format”:
(HH returns only hours)

• DO NOT forget that 00 hours should be 24 rather than 00, so we use find & replace, as below:
(you can see this is in calculation above)

Please let me know if you know an easier way or found an error in my thinking, otherwise you are welcome, it took me a day to work out.

Bubble, can we have a Loop function please?, If you like, just allowed a limited it to a reasonable extent number of steps and loops.

Kind regards

Alex

4 Likes

I don’t really get what you’re trying to do and why. Afaik Bubble stores dates as UNIX timestamp, which is independant from timezones. The timezone is only used clientside when the timestamp is shown to the user.

In the Datepicker, we cannot select timezone.

So when one selects just a date (no time), in another timezone it will will become a different date. If you select 12th July in Moscow today, in London it will show as 11th July. If you have dependent actions relative to 12th July, 11th July date will break logic of these actions.

I also had this issue to for an Event app of mine and here is the solution I came up with, it uses some simple javascript and the geographic location box. Or something close to this (I recall DST tripping me up)

Geoff | Top Shelf Templates
Check out a Best Selling Bubble Template
Check out one of The Most Used Bubble Template (FREE)

1 Like

I guess could be done that way too, I just didn’t want to ask for user’s location.

Some javascript:

`(new Date()).getTimezoneOffset()`

For my browser it returns -600, which means I’m currently ahead of UTC by 10 hours.

2 Likes

You can also get the current user’s timezone by “current date/time:formatted as Z”.

2 Likes

Thank you.

I wish I knew JS.

Could you suggest how to adjust a date to another timezone using JS?

To alter a date to UTC, add the offset after converting it from minutes to milliseconds. The trickiest part is getting the date from Bubble into javascript reliably, allowing for empty values …

(Edit - corrected)

Do you want a mechanism for the user to enter a date/time for a different timezone than they are in? This is a lot harder than UTC, because you also need to work out the timezone offset for the target timezone.

To do this, its best to use a library (for example moment-timezone.js), or call an API service that does it for you (like the plugin by Coaching Bubble does).

Edit … looking at @gf_wolfer 's post above, it is somewhat similar haha : )

@funwtp I just thought of a (lot) simpler solution.

Bubble can format a date to a text, using a different timezone, so it does the messy part of the timezone lookup.
Although it doesn’t offer the reverse, we can calculate the reverse, with the following logic:

Entered date - current date (target timezone) + current date (local timezone)

This means some messing around, as the date formatted to a text is no longer a Bubble date, so I pass it to javascript to convert. For consistency, I pass all three dates with the same text format.
Custom format: `yyyy-mm-dd HH:MM:ss.L`

On the target, choose the other timezone when choosing the format.

`tPick ='`Picker’s value:formatted as yyyy-mm-dd HH:MM:ss.L`';`
`tLocal = '`Current date/time:formatted as yyyy-mm-dd HH:MM:ss.L`';`
`tTarget = '`Current date/time:formatted as yyyy-mm-dd HH:MM:ss.L`';`
`if (tPick && tLocal && tTarget) {`
`(new Date(tPick)).getTime() - (new Date(tTarget)).getTime() + (new Date(tLocal)).getTime();`
`}`

1 Like

Actually, @mishav, Bubble can almost do this entirely in “vanilla” Bubble (without resorting to a JavaScript action – which isn’t that hard of course – I just thought this was very interesting): It turns out that an Input set to Content Type: date (or presumably date2, if one prefers Euro ordering) WILL take a text value as its “Initial Value”. Try this:

• Make an Input on the page, set its content type to date.

• Somewhere else on the page (like the default value in a custom state, or from the database, doesn’t matter) have a text value in formatted like a date (e.g., “1984-05-30” or something like “05/30/1984” – though using the first version will prove my case).

• Use that dynamic value as the Initial Value for the Input.

• You will note that the Issue Checker throws an issue about this (it will tell you that Initial Value should be a date but right now it is a text). So you couldn’t deploy this to live… but let’s explore a bit…

• SO, preview the page. You will note that the Input’s default value actually SHOWS THAT DATE, formatted as 05/30/1984.

• Does its value property contain a date value? YES, yes it does. This can be shown by adding a text element to the page as shown in my screenshot below:

This suggests a couple of things to me:

1. As I bitched about in another thread, it’s fairly clear that Bubble’s date functions are enabled by moment.js and moment-timezone. However, the implementation is not entirely complete.

2. Thus, there’s very little reason there shouldn’t be a “:formatted as… date” operation for text data types. And, further, those could also have the features of moment-timezone.

3. While it’s possible that the Input element is falling back to JavaScript date manipulation functions and not utilizing moment.js (or moment.js is throwing the deprecation error), I get the funny feeling that what the Input element is doing here is actually creating a moment from text value and expecting the formatting to be mm/dd/yyyy. (So, in this case, it’s falling back to JS date manipulation functions and my text should probably be stored as “05/30/1984” and not “1984-05-30”.)

3a. If I’m right about #3, it is the ISSUE CHECKER that is wrong here. The input is fully capable of converting a text to date, it’s just that we are being erroneously blocked by the issue checker.

3b. If I’m wrong about #3, all that means is that the input is using JS date manipulation. It is, at any rate, creating a date type object from text. (Caveat: You will see that the date or moment created was created in MY TIME ZONE and I have no way of changing that except by the means that you describe above.)

So, the story is (1) there REALLY should be a text:formatted as… date operator for texts that uses moment/moment-tz to create date objects from text. (Also, I will note that there is clearly already this functionality in the API connector.) and (2) the issue checker and Input element are bugged – the input element SHOULD take texts without complaining as it DOES convert text to dates, the Issue Checker should not raise a flag over this. Of course, the “right” way for Bubble to do this would be with an operator.

Interesting, yeah?

1 Like

Very nice, @keith.

Agree, lets call it parse, and have options for date, number, geographical address, etc. to deprecate all the messy hacks with conversions.

Yes I sometimes get error messages from moment.js without even loading its library … I think that the libraries Bubble loads should be usable by our apps as well, why load moment a second time and create bloat?

Its like the issue checker doesn’t know the input element’s API, which is understandable considering its light documentation.

1 Like

Misha,

Would you be so kind to help me to correctly wrap this expression into Toolbox Expression “formal”:

setInterval (function() {var x = \$(‘div[id^=d]’).length; return x;},1000); (i am trying to get count of certain elements with ID of “d” on my page as they appear)

It seems to work when I console.log the result but it doesn’t seem to return correct value to Expression element so I can pull and it it?

My JS ability is very poor. Thank you in advance.

This will run your anonymous function asynchronously, so its not really appropriate for the Expression element.

Instead, run it either in a HTML element, or in Run Javascript action. Add an element JavascriptToBubble to capture the value back to bubble.

Then change the `return x` to be `bubble_fn_something(x)`.

For reference, see

And possibly Keith’s video:

2 Likes

Thank you, Sir! All works perfectly!