Overview



The localization is one of the most important aspects of every software product. It doesn’t matter if it’ll be used in different languages, it will quite certainly be used in different timezones. The risk of shipping a product with no (or limited) i18n support is neglectful only in case your targeted customer base is located in a specific geographical location and you are absolutely certain it will not pose a problem. Nonetheless, if you decide to expand your business in the future, be 100% sure that at some point you’ll need to take care of this.

Unfortunately, the bigger part of the developers, technical leads and managers are simply not aware of the specific problems. As a consequence of that, 2/3 of the software products worldwide will not provide the correct time under certain circumstances.

Let’s define the problems, both general and concrete, and think of appropriate resolutions.



Taking the time into consideration



At first sight, there is nothing very special about holding the user’s time. Let’s say we have a 3-tier web application and a bunch of users using the system. There are various forms, some of which have time fields and most of the actions need a timestamp.



Defining the problem



The different times are processed by a server and placed in a persistent storage. But what time exactly will you store on the backend ? Is your server in the same timezone as your storage ?

The problem with storing the time as it is put from the user is that the user might be located in a different timezone. If you directly store the input, you’ll have a localized time in a specific timezone. If someone from a different part on the globe decide to extract that time, how could he figure the exact time zone so he can adjust the appropriate offset ?

He will not be able to.

Thinking of resolutions



The first thing that comes to mind is to store the user’s offset, along with the time, in the persistence storage (let’s say a database). Although it’s a possible solution, it’s not the smartest one. You’ll need an additional column for that and it feels dirty.

A better approach would be to use the Coordinated Universtal Time format.



Storing the time in UTC format



The best practice is to store the time in the Coordinated Universal Time (UTC) format. All the timezones around the globe are represented by an offset from this time, meaning that having the user’s offset for every request can help us easily convert the UTC in the correct timezone.



Ways of obtaining the timezone information from the client



So far so good. But how exactly would you extract the timezone information from the client’s browser ? Through the HTTP headers ?

Nope, you’ll not find such information there.



Using Date.getTimezoneOffset() to acquire the offset



A more realistic solution would be to use JavaScript’s Date.getTimezoneOffset() method. It’s a simple method from the standard JS library that would allow us to obtain the timezone offset. At first sight, it feels like the best solution. We send the offset to the server, convert the time to UTC and store it in the database. For every consequent call for any of the timings, we use the same method to get the offset and produce a proper time for the client at hand.

And that will work properly most of the time. However, if you want to create a robust software, “most of the time” just doesn’t sound right. Which brings us to the reason behind that.



The Daylight Time Savings (DTS)



Simply using the offset to convert from and to UTC will not work due to the Daylight Time Savings (DTS) settings used in most of the western nations.

DST is used.

DST is no longer used.

DST has never been used.

Source: Wikipedia DST has never been used.

And guess what ? The Date.getTimezoneOffset() will just get you the offset, regardless the DTS. Meaning that you can’t depend on it for a precise metric.

The possible solutions



I see three possible solutions to this problem.



Solution #1



Ask the user to specify his timezone from a list of possible choices.

MSDN Timezone list

Whatever his choice is, store it in the database. Note that we don’t store the offset, we store the timezone which will allow us to utilize the default mechanism provided by most of the contemporary frameworks. When a request for a time comes, retrieve the timezome and use the appropriate methods on the time to convert it to the correct timezone. This will take the DTS settings under consideration.

Example code from MSDN:

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00); string easternZoneId = "Eastern Standard Time"; try { TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId); Console.WriteLine("The date and time are {0} UTC.", TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)); } catch (TimeZoneNotFoundException) { Console.WriteLine("Unable to find the {0} zone in the registry.", easternZoneId); } catch (InvalidTimeZoneException) { Console.WriteLine("Registry data on the {0} zone has been corrupted.", easternZoneId); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 DateTime easternTime = new DateTime ( 2007 , 01 , 02 , 12 , 16 , 00 ) ; string easternZoneId = "Eastern Standard Time" ; try { TimeZoneInfo easternZone = TimeZoneInfo . FindSystemTimeZoneById ( easternZoneId ) ; Console . WriteLine ( "The date and time are {0} UTC." , TimeZoneInfo . ConvertTimeToUtc ( easternTime , easternZone ) ) ; } catch ( TimeZoneNotFoundException ) { Console . WriteLine ( "Unable to find the {0} zone in the registry." , easternZoneId ) ; } catch ( InvalidTimeZoneException ) { Console . WriteLine ( "Registry data on the {0} zone has been corrupted." , easternZoneId ) ; }

Solution #2



This is not the clearest solution, but I guess it’ll work.

We got Date.getTimezoneOffset() method which will return the user’s offset with or without DTS. Isn’t there a flag which says if DTS is at hand ? Some method to tell us if a daylight time change is in place ?

There is not.

But you can use a little hack, nicely packed within the prototype of the Date class in Javascript.

Date.prototype.stdTimezoneOffset = function() { var jan = new Date(this.getFullYear(), 0, 1); var jul = new Date(this.getFullYear(), 6, 1); return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); } Date.prototype.dst = function() { return this.getTimezoneOffset() < this.stdTimezoneOffset(); } 1 2 3 4 5 6 7 8 9 Date . prototype . stdTimezoneOffset = function ( ) { var jan = new Date ( this . getFullYear ( ) , 0 , 1 ) ; var jul = new Date ( this . getFullYear ( ) , 6 , 1 ) ; return Math . max ( jan . getTimezoneOffset ( ) , jul . getTimezoneOffset ( ) ) ; } Date . prototype . dst = function ( ) { return this . getTimezoneOffset ( ) < this . stdTimezoneOffset ( ) ; }

It makes use of the assumption that if there are two dates, for the first of which we know that is without DTS and for the second that is with DTS, from the same timezone, we can use them for comparison to find out if our own time is with DTS or not.

This could allow us to store a correct offset for the user in the database. Nevertheless, I'm not convinced that there are two dates for which we know for sure they meet the criteria. But it’s an automatic solution. Also, the fact that the browser (and therefore the JS engine) thinks that it knows the offset, doesn’t mean the user really wants that setting or even knows that the setting is there.



Solution #3



Ask the user for his timezone in a droplist. Provide an auto selection “educated guess” based on the offset provided from Javascript. Once entered, keep checking the offset value behind the scenes for inconsistencies. If you detect some – ask the user to select a new timezone.

Personally I think it’s the best approach, although not automatic it provides a coherent combination of manual precision and automatic selection. Whatever approach you decide is best for your case, make sure to configure the server’s time settings to UTC. Otherwise, you’ll run into hideous issues when using your framework’s time conversion methods.

That’s all from me on this matter, hope this information will help you make the right decision. ;)

Kosta Hristov ( 34 Posts Hi there ! My name is Kosta Hristov and I currently live in London, England. I've been working as a software engineer for the past 6 years on different mobile, desktop and web IT projects. I started this blog almost one year ago with the idea of helping developers from all around the world in their day to day programming tasks, sharing knowledge on various topics. If you find my articles interesting and you want to know more about me, feel free to contact me via the social links below. ;)

No related posts.

Like the article ? Share it ! ;)