OutSystems: How to handle multi time zone applications?

 

As the Disney song claims, “it’s a small world after all…” For us developers the lyrics of this song reasonate even more. It’s inevitable that at some point we have to develop an application that will be used worldwide. And this is a good thing! But you may face a few challenges.

Near Partner - GEEK ALERT!!!Subject to spontaneous outbursts of geek speech!

Every programmer that has worked in projects that cover more than one geographic location, and where the time displayed to the user is important, has felt the pain of working with  multi time zone. In Outsystems it is no different.

Fortunately, as the saying goes “there’s an app for that”, or in our case “there’s a Forge component for that”:

Time Zone component actions:

Time Zone component actions:

With this component you can do several actions including the important:

  • GetCurrentTimeZone – returns a TimeZone record containing the current time zone details of the system where the app is running.

This time zone record is composed by:

  • Identifier – unique identifier for the time zone (ex: UTC, India Standard Time, etc.)
  • StandardName – Standard name for the time zone (ex: UTC, India Standard Time, etc.)
  • DisplayName – Display name for the time zone (ex: (UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi)
  • UtcOffset – Offset in minutes from the UTC time zone to this time zone (ex: for India Standard Time is plus 330 minutes from UTC)
  • SupportsDaylightSaving – True if the time zone supports daylight savings, false if not
  • IsDaylightSaving – True if the time zone is currently in daylight savings, false if not

With this component you can also get the time zone by location (Lisbon, Paris, etc.), by Windows/java identifier or by IANA code.

You can use ConvertFromTimeZone to convert between two time zones, ConvertFromUTC to convert from the UTC time zone to another one and ConvertToUTC to convert to the UTC time zone.

When you are dealing with different time zones you should keep the necessary datetimes in your database in the UTC time zone so it’s easier to convert them to the user Time zone using the ConvertFromUTC and the ConvertToUTC actions.

With this component it is easy to get the server time zone using the action GetCurrentTimeZone. What if I need the user’s time zone? That is the real problem for which Outystems doesn’t give us an easy solution. So we need to resort to javascript.

 

Getting the user’s time zone

There isn’t a definitive way to get the correct time zone of the user’s browser. The best option would be to let the users define their own time zone and then convert the server times using the actions available in the Time Zone component. However, if you really need to be able to detect the user’s browser time zone there is no other way but JavaScript.

Even with JavaScript there is an easy way and a hard way. The first one returns correct values for the time zone but isn’t supported in all browsers (I’m looking at you IE 11).  The second one (and in my opinion quite inefficient) will get you the current UTC offset but may not be able to return the exact time zone location the user is in. As you can see, both options are valid but each one comes with a catch. Depending on your project requirements, you need to pick the one that is a better fit for your situation.

 

Easy way – Internationalization API

The Intl object provides a series of tools for language sensitive string comparison, number formatting, and date and time formatting. For the task in hand we will be using this expression:

Intl.DateTimeFormat().resolvedOptions().timeZone

Internationalization API

This expression, in supported browsers, will return the standard IANA name for the time zone. With this name you can use the action GetIANATimeZone from time zone component to get the correct time zone record for that time name.

 

Hard way – offset from UTC

When the easy way doesn’t work and is enough to know the offset between the user’s browser time zone and UTC, you only need:

new Date().getTimezoneOffset()

offset from UTC

This will return the difference in minutes between UTC time and the browser’s time. Note that if the times we need to change are in UTC and we need to change them to the user’s time it’s simple math. But if we need more details about the user’s time zone, we‘ll have to make an educated guess using that offset. A simple way of doing this is to get all the system time zones with the GetSystemTimeZones action and cycle through them until finding one with the correct offset. Unfortunately, this will most likely not get the correct time zone but the first one with that offset.

Implementation

For testing the functionalities of the TimeZone component and how to get the user’s time zone we created a page to test the functionalities described below:

TimeZone component test page

In the first line we have the server time and time zone. In the second one, the server time converted to UTC. At last, the client time and time zone info.

getCurrentTimeZone

Server time and time in UTC are done in preparation. We get the server time zone with getCurrentTimeZone and then we feed the server time and the server time zone identifier to ConvertToUTC to get the converted datetime.

 

For the user time zone if we don’t have it already before entering the page, we can only get it after the page is loaded. The logic for getting the user time zone is encapsulated in a webblock that returns the user time zone to the parent page.

IANA and Offset buttons

 

 

 

 

 

In this webblock we kept the script that handles the necessary javascript, an input to keep the values returned by the javascript and 2 buttons: one for when we can get the IANA name and one for when we must get it by the offset.

 

The Script

Download the script here!

 

Button IANA

IANA

If we have the IANA name we just need to use the GetIANATimeZone action and the trigger the ReturnTimezone event (Yay for outsystems 11, but if can’t use it, use the old notify to return the values that you need) that returns the timezone record to the parent.

 

Button Offset

Button Offset

 

By offset, as mentioned before, is just inefficient. You’ll most likely not get the correct time zone, but you will have the correct offset to do your calculations. We get the systems time zones and then iterate trough them until we find one with the same offset and then return the timezone using the ReturnTimezone event.

parent screen returnTimezone

In the parent screen, we create a handler for the returnTimezone event that will do the necessary conversions and refresh the necessary parts of the screen that will now display the correct information.

As you can see the change will not be immediate. There will be a few seconds before the event is triggered and you can display the correct times. This can be solved by using this logic on an entry screen and keeping the necessary info about the time zone in session variables so when you enter another screen you can already do the necessary conversions before the page is loaded.

 

Conclusion

Converting times between time zones isn’t difficult. We already have existing components that do the job for us.
Keep the date times in your database in UTC so it’s easier to convert to any time zone you’ll want in the future.
Regarding the time zone of the user, it’s easier if you know it beforehand (let the user define it). But, let’s face it, normally this isn’t possible. That’s why we need to implement one of these options. Your job is to understand which one is better to solve your problem!


 

Outsystems Module for multi time zone applications

We developed a working case to help you implement this solution!
Download here:

Bruno Marques

Outsystems developer, avid learner and a all-around geek.