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 appication 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:
puts(TZInfo::Timezone.all_country_zones.map { |tz|
offset = tz.current_period.utc_offset / 3600
[tz.name, offset]
}.sort_by { |tz| tz[1] }.map { |(tz, offset)|
"| #{tz} | `UTC#{offset >= 0 ? '+' : ''}#{offset}` |"
}.join("\n"))
If you need to support timezone conversion for Liquid templates in your Rails app, then I hope this post was helpful!