All posts

2 min read Nathan Broadbent

Timezone Conversion in Liquid Templates, for Ruby on Rails

Close-up of an analog clock.

Our HTML/CSS templates support Shopify’s Liquid syntax to include dynamic data and logic. Liquid supports a lot of filters and tags out of the box, including a function to format dates. However, some of our customers needed to display a date in a specific timezone, and Liquid doesn’t have any built-in support for timezone conversion.

Fortunately, it’s very easy to create your own Liquid filters, and Rails makes it easy to convert dates and times into different timezones.

I saw that some other companies have created their own Liquid filters for timezone conversion, but I couldn’t find any open source filters or blog posts. I’ve decided to share the Liquid filter that we use to provide timezone conversions in a Ruby on Rails application.

  • Add this file to lib/liquid/filters/in_time_zone.rb:
# frozen_string_literal: true

module Liquid
  module Filters
    module InTimeZone
      TIMEZONES = TZInfo::Timezone.all_country_zones.map(&:name).sort.freeze

      def in_time_zone(input, timezone)
        time = if %w[now today].include?(input)
          Time.zone.now
        elsif input.is_a?(String)
          begin
            Time.zone.parse(input)
          rescue StandardError
            nil
          end
        elsif input.is_a?(Time) || input.is_a?(Date)
          input
        end
        return input if time.nil?
        return time unless TIMEZONES.include?(timezone)

        time.in_time_zone(timezone)
      end
    end
  end
end

Liquid::Template.register_filter(Liquid::Filters::InTimeZone)
  • Add an initializer at config/initializers/liquid.rb to require the Liquid filter when your application boots:
# frozen_string_literal: true

# Require all of our custom Liquid filters and tags
Dir.glob(Rails.root.join('lib', 'liquid', '**', '*.rb')).each do |f|
  require f
end

Now you will be able to use the in_time_zone filter in your Liquid templates.

  • Show a user’s created_at timestamp in the New York timezone:
  {{ user.created_at | in_time_zone: "America/New_York" | date: "%Y-%m-%d %H:%M" }}
  • Show the current time in New York:
  {{ 'now' | in_time_zone: "America/New_York" | date: "%Y-%m-%d %H:%M" }}


We’ve also added a timezone table to our documentation, so you can see all of the available timezones and UTC offsets. I wrote a short Ruby script to generate the table rows:

Offsets are calculated for the current instant, including daylight saving time. They can change during the year. The formatter keeps minutes, so zones such as Asia/Kolkata and Asia/Kathmandu are not rounded to whole hours.

now = Time.now.utc
rows = TZInfo::Timezone.all_country_zones.map do |tz|
  offset = tz.period_for_utc(now).utc_total_offset
  hours, remainder = offset.abs.divmod(3600)
  minutes = remainder / 60
  label = format('UTC%s%02d:%02d', offset.negative? ? '-' : '+', hours, minutes)
  [tz.name, offset, label]
end

puts rows.sort_by { |name, offset, _| [offset, name] }.map { |name, _, label|
  "| #{name} | `#{label}` |"
}.join("\n")



If you need to support timezone conversion for Liquid templates in your Rails app, then I hope this post was helpful!

More posts

Try DocSpring with your own documents

Upload a PDF or a Word document, or create an HTML template, then send a test request. No credit card needed.

Blog posts and product news by email

New articles and product changes, once a month.