Reprise: 4 More Tips to Deal with Time Zones
In our last post, Time Zones, that thorn in our side, we’ve been talking about some difficulties and ways to avoid problems when setting time zones in applications. We know this is a really important issue, that’s why we decided to list some additional advice.
Queries
As we previously mentioned on Time Zones, that thorn in our side, Rails will store dates in UTC, therefore, each query must keep this into consideration. But ActiveRecord will neatly turn each date it receives into UTC so we don’t have to deal with this problem.
Comment.where(“created_at >= :from AND created_at < :one_hour_after”, from: Time.current, one_hour_after: Time.current.advance(hours: 1))
Related Post: Time Zones, that thorn in our side
Localization per User
One of the most common uses of an app with multiple time zones is related to how the data connected to time is shown to each particular user. If we don’t want the user to be confused, we MUST show them daily both dates associated to their own actions as well as the dates associated to the actions of other users in other areas of the world in a format the user can understand. The user only cares about seeing a date, having a watch, and knowing that a given action was taken X minutes ago, regardless if it is in UTC, EST or whichever time zone.
We can then set the application time zone only for the given particular request, with the time zone selected by the user. Using around_filter under ApplicationController, or under the specific ActionController, we can rest assured that the dates will be calculated using the user’s time zone.
around_filter :request_time_zone, :if => :current_userdef request_time_zone(&block)Time.use_zone(current_user.time_zone, &block)end
For starters, this requires the user to have a time zone set. We then may either infer it somehow, or simply ask the user to set it.
If we plan to infer it, let’s remember it’s not the same to store the string with the location the user is at (i.e.: America/Argentina/Buenos_Aires) than the difference versus UTC time (i.e.: -0300). If the user’s time zone changes the time one hour back or ahead to save energy, we can infer this change using the location string but not using the value of the difference versus UTC, as not every zone in that time zone will make this change.
We can use gems like this one to infer the current time zone by making a request to the geonames’ API, (the result will depend on the coordinates sent).
TZinfo and TZinfo-data
It is important to understand how Ruby knows what the time on a specific time zone was years ago, and if it was in daylight saving time or not. This can be checked with the Time.current.dst? method in Rails, or with other similar information. In this process, tzinfo makes all the calculations depending on the historical data of the changes in a given time zone. This data can be extracted from the system hosting the server, or from tzinfo-data, a gem that compiles all this information. If we are not aware of how often the server’s host updates this information or not, it may be wise to make the effort to keep the tzinfo-data database running on the server updated.
Tests
The main problem with tests is that they are designed and built under the time zone of the machine they will be executed on, so both time zones are the same. This is why these errors may be found after the deployment into production or, best case scenario, when they’re executed in Travis or on a computer with a time zone different from the one the developer is working on, for example.
A gem that allows us to find these problems locally is zonebie which, in a nutshell, will randomly set the time zone before running each test. But be careful because even though tests run correctly, it doesn’t necessarily mean the problem has been solved, as it could be that the randomly chosen time zone has not generated, for example, a “date change”. We could say that, the more often the tests run, the higher the odds of finding these errors.
We hope Time Zones aren’t a problem for you after reading this post! Remember there is one more post giving tips about this issue: Time Zones, that thorn in our side.
Yeah, well, that’s just, like, my opinion, man
Posted by Gastón Ponti (gaston.ponti@wolox.com.ar)