Handling User Timezones in Ruby on Rails: A Comprehensive Guide

August 14, 2024

Handling User Timezones in Ruby on Rails: A Comprehensive Guide

In today’s globalized world, displaying times in a way that suits each user’s local timezone is crucial for user experience. This guide will walk you through adding and managing user timezones in a Ruby on Rails application using Devise, and how to display timestamps in a user-friendly format.

Adding Timezone Support to Your Rails Application

1. Add a Timezone Column to the User Model

First, you need to add a timezone column to the users table. This allows each user to have a personalized timezone setting.

Generate a migration:

rails generate migration AddTimezoneToUsers timezone:string
rails db:migrate

2. Permit the Timezone Parameter in Devise

To allow Devise to handle the timezone parameter during sign-up and profile updates, override the RegistrationsController:

Generate the controller if you haven’t already:

rails generate devise:controllers users

Update app/controllers/users/registrations_controller.rb:

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]

  protected

  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:timezone])
  end

  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:timezone])
  end
end

3. Update Your Routes

Ensure your routes use the custom controller:

devise_for :users, controllers: {
  registrations: 'users/registrations'
}

4. Add Timezone Selection to Forms

Sign-Up Form
Modify app/views/devise/registrations/new.html.erb to include a timezone dropdown:

<div class="field">
  <%= f.label :timezone %><br />
  <%= f.select :timezone, ActiveSupport::TimeZone.all.map { |tz| [tz.name, tz.name] }, {}, class: "form-control" %>
</div>

Edit Profile Form
Similarly, update app/views/devise/registrations/edit.html.erb:

<div class="field">
  <%= f.label :timezone %><br />
  <%= f.select :timezone, ActiveSupport::TimeZone.all.map { |tz| [tz.name, tz.name] }, {}, class: "form-control" %>
</div>

5. Apply User’s Timezone Throughout the Application

Add a method to your ApplicationController to use the user’s timezone:

class ApplicationController < ActionController::Base
  around_action :set_time_zone

  private

  def set_time_zone(&block)
    timezone = current_user.try(:timezone) || 'UTC'
    Time.use_zone(timezone, &block)
  end
end

Displaying Timestamps in a User-Friendly Format

To ensure that timestamps are displayed in a readable format with AM/PM notation:

1. Format the Time with AM/PM

Use strftime to format the timestamp in your views. For example:

<td><%= click.created_at.in_time_zone(current_user.timezone).strftime("%Y-%m-%d %I:%M:%S %p") %></td>

This will display timestamps in the format:

2024-08-03 02:37:40 AM

2. Example Code

Here’s how you would incorporate this into your view:

<td><%= click.created_at.in_time_zone(current_user.timezone).strftime("%Y-%m-%d %I:%M:%S %p") %></td>

Committing Your Changes

To document these changes in your version control, use a clear and descriptive commit message. For example:

Format timestamps with AM/PM for user-friendly display

- Updated the view to format `created_at` timestamps with AM/PM notation.
- Converted timestamps to the user's timezone before formatting.
- Applied `%I:%M:%S %p` format to display hours in 12-hour clock with AM/PM indicator.

This change improves readability for users by displaying times in a more conventional AM/PM format.

Summary

Handling user timezones in a Rails application involves:

  1. Adding a timezone attribute to the users model.
  2. Permitting and handling timezone parameters in Devise.
  3. Displaying timestamps in a user-friendly format, including AM/PM notation.

By following these steps, you enhance user experience by ensuring that times are displayed according to each user's local timezone and in an easily readable format.


Follow Me