Skip to content

Instantly share code, notes, and snippets.

@mateusmsf94
Created January 13, 2026 22:40
Show Gist options
  • Select an option

  • Save mateusmsf94/c8fe11d9adb434b69fa2242b7f6488ce to your computer and use it in GitHub Desktop.

Select an option

Save mateusmsf94/c8fe11d9adb434b69fa2242b7f6488ce to your computer and use it in GitHub Desktop.
Rails Time Best Practices

Best Practices for Handling Time in Rails

Based on a Rails 8 setup with Google Calendar and Geocoder gems, here are essential best practices for handling time in a scheduling application.

1. The Golden Rule: Store in UTC, Display in Local

  • Database: Always keep config.active_record.default_timezone = :utc (this is the default). Never store local times in the database.
  • Why: It makes daylight saving time (DST) calculations and cross-timezone scheduling manageable. If you store "9:00 AM" without a zone, it’s ambiguous.

2. Configure the Application Default

In config/application.rb, set a sensible default for the application logic, even if the DB is UTC.

# config/application.rb
config.time_zone = "Brasilia" # Or your primary target audience's zone

This ensures that Time.zone.now defaults to this zone if a user-specific zone isn't set.

3. Handle User Timezones

Since this is a scheduling app, every user (and potentially every appointment) needs a specific timezone.

  • Add a column: Add time_zone to your users table.
  • Validation:
    validates :time_zone, inclusion: { in: ActiveSupport::TimeZone.all.map(&:name) }
  • Usage: Use an around_action in your ApplicationController to set the context for each request.
    around_action :set_time_zone, if: :current_user
    
    def set_time_zone(&block)
      Time.use_zone(current_user.time_zone, &block)
    end

4. Code "Do's and Don'ts"

  • DO use Time.current or Time.zone.now. These respect the configured Time.zone.
  • DO use 1.day.from_now or Date.current.
  • DON'T use Time.now. It uses the server's system time and ignores your Rails timezone configuration, often leading to subtle bugs.
  • DON'T use Date.today. It also relies on system time.

5. Google Calendar Integration

Using google-apis-calendar_v3 requires strict time formats.

  • Format: Always convert times to ISO 8601 / RFC 3339.
    start_time: appointment.start_at.iso8601
  • Zone: Pass the timezone explicitly to Google's API event payload to ensure the event shows up correctly in the user's GCal.

6. Geocoder & Timezone Detection

Use geocoder to auto-detect a user's timezone upon sign-up based on their IP address:

# In a callback or service
results = Geocoder.search(user_ip)
timezone = results.first&.data['timezone'] # generic example, depends on provider

Tip: Also consider using JavaScript (Intl.DateTimeFormat().resolvedOptions().timeZone) on the frontend to detect the browser's timezone and populate a hidden field during registration.

7. Testing

Use Rails' built-in time helpers to "freeze" time during tests. This prevents flaky tests that fail only at night or across month boundaries.

# test/test_helper.rb
include ActiveSupport::Testing::TimeHelpers

# In your test
travel_to Time.zone.local(2024, 11, 24, 10, 0, 0) do
  # Perform assertions assuming it's always this specific time
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment