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.
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”:
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.
Getting the user’s time zone
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:
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:
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.
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:
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.
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.
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.
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.
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.
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!