Skip to content

Instantly share code, notes, and snippets.

@itchy
Last active December 21, 2015 23:39
Show Gist options
  • Save itchy/6383770 to your computer and use it in GitHub Desktop.
Save itchy/6383770 to your computer and use it in GitHub Desktop.
Setting I18n localizations to format times based on user's timezone
class ApplicationController < ActionController::Base
around_filter :set_i18n_locale_from_current_user
def set_i18n_locale_from_current_user
org_timezone = I18n.current_timezone
if current_user
I18n.current_timezone = current_user.timezone
end
yield
ensure
I18n.current_timezone = org_timezone
end
end
# From
# https://gist.github.com/alexisbernard/179712
# with updates including
# _date_format(str, format)
# to allow /, - or . as separators
# AND
# match ruby params for _parse && parse
# https://gist.github.com/itchy/6383770
class Date
class << self
def _date_format(str, format)
format ||= :default
date_format = I18n.translate("date.formats.#{format}")
date_format[/([\.\/-])/]
format_seperator = $1
str[/([\.\/-])/]
str_seperator = $1
date_format.gsub!(format_seperator, str_seperator) if format_seperator && str_seperator
date_format
end
def _parse_with_i18n(str, comp=true, format = :default)
date_format = _date_format(str, format)
date = Date._strptime(str, date_format) || _parse_without_i18n(str)
date = _parse_without_i18n(str) if date[:leftover]
date[:year] += increment_year(date[:year].to_i) if date[:year]
date
end
alias_method_chain :_parse, :i18n
def parse_with_i18n(str, comp=true, start=ITALY, format = :default)
date_format = _date_format(str, format)
date = Date.strptime(str, date_format)
Date.new(date.year + increment_year(date.year), date.month, date.day)
rescue ArgumentError
parse_without_i18n(str)
end
alias_method_chain :parse, :i18n
def increment_year(year)
if year < 100
year < 30 ? 2000 : 1900
else
0
end
end
end
end
# in initializers
module I18n
def self.current_timezone=(tz='UTC')
Thread.current[:current_time_zone] = ActiveSupport::TimeZone.find_tzinfo(tz)
end
def self.current_timezone
Thread.current[:current_time_zone] || ActiveSupport::TimeZone.find_tzinfo('UTC')
end
module Backend::Base
def localize_with_timezone(locale, object, format = :default, options = {})
raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
object = object.in_time_zone(I18n.current_timezone) if object.respond_to?(:in_time_zone)
localize_without_timezone(locale, object, format, options = {})
end
alias_method_chain :localize, :timezone
end
end
@parkranger
Copy link

I wonder if it is thread safe. Variable @current_time_zone seems to be a global one because of self. However, I have not looked for it, but if the I18n.locale is implemented the same way we should do so too.

Also function should be named set_i18n_timezone_from_current_user and not replace the set_I18n_local_from_current_user (typo?).

What you do at module Backend::Base looks interesting, but that all I can say here.

@itchy
Copy link
Author

itchy commented Aug 31, 2013

Thanks Jens -- I updated the gist to have I18n#current_timezone be thread safe

@itchy
Copy link
Author

itchy commented Sep 3, 2013

Update date.rb to match Ruby args

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment