What Is the Time of Now? Navigating Time Zones in Modern Applications

Time, a seemingly simple concept, becomes surprisingly complex when dealing with applications that span different geographical locations. This article explores the challenges of accurately displaying time to users in various time zones, drawing from practical experience in time tracking and software development.

One common pitfall is the accidental leakage of times in the wrong time zone. While methods like Sam’s approach work well for JavaScript rendering, they often fail when dealing with HAML/erb, CSV exports, or emails triggered by background jobs.

A robust solution involves storing a time_zone column for each user and storing all actual times as a timestamp without time zone in PostgreSQL. An around_action can then be used to set Time.zone on each request for the current user. For background jobs, wrapping jobs in TimeZone.in(@user) {} is crucial. The challenge, however, lies in ensuring this practice is consistently followed.

Alt text: A clock displaying multiple time zones, highlighting the complexity of time management across different locations.

The biggest hurdle arises when displaying time for user B in user A’s interface, when they reside in different time zones. Imagine user A on the west coast needing to see when user B, working in a factory on the east coast, started their shift. Displaying the time in user A’s time zone would be inaccurate. While displaying it in user B’s time zone would be correct for user B, what if the same interface needs to show data for user C, who lives in Central time?

To address this, the industry is moving away from per-request time zones towards making models time zone aware. When loading any object with time columns, the appropriate time zone is determined from relevant associations, typically the user but potentially their home location.

module TimeZoneAware
  extend ActiveSupport::Concern

  included do
    around_action :set_time_zone, if: :current_user

    def set_time_zone(&block)
      Time.use_zone(current_user.time_zone, &block)
    end
  end
end

This approach enables accurate time representation across diverse user bases. An example implementation can be found at https://gist.github.com/ghiculescu/d8148f60a4e8c8b0fa7ceb77df49b139.

In conclusion, accurately displaying time in applications requires careful consideration of time zones. By storing time zone information, setting time zones appropriately, and making models time zone aware, you can ensure a consistent and accurate time experience for all users, regardless of their location. Consider implementing time zone linters to enforce best practices and prevent accidental errors.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *