require 'rails_admin/support/i18n' module RailsAdmin module Support class Datetime # Ruby format options as a key and momentjs format options as a value MOMENTJS_TRANSLATIONS = { '%a' => 'ddd', # The abbreviated weekday name ("Sun") '%A' => 'dddd', # The full weekday name ("Sunday") '%b' => 'MMM', # The abbreviated month name ("Jan") '%B' => 'MMMM', # The full month name ("January") '%d' => 'DD', # Day of the month (01..31) '%D' => 'MM/DD/YY', # American date format mm/dd/yy '%e' => 'D', # Day of the month (1..31) '%F' => 'YY-MM-DD', # ISO 8601 date format '%H' => 'HH', # Hour of the day, 24-hour clock (00..23) '%I' => 'hh', # Hour of the day, 12-hour clock (01..12) '%m' => 'MM', # Month of the year (01..12) '%-m' => 'M', # Month of the year (1..12) '%M' => 'mm', # Minute of the hour (00..59) '%p' => 'A', # Meridian indicator ('AM' or 'PM') '%S' => 'ss', # Second of the minute (00..60) '%Y' => 'YYYY', # Year with century '%y' => 'YY', # Year without a century (00..99) } class << self include RailsAdmin::Support::I18n def delocalize(date_string, format) return date_string if ::I18n.locale.to_s == 'en' format.to_s.scan(/%[AaBbp]/) do |match| case match when '%A' english = ::I18n.t('date.day_names', locale: :en) day_names.each_with_index { |d, i| date_string = date_string.gsub(/#{d}/, english[i]) } when '%a' english = ::I18n.t('date.abbr_day_names', locale: :en) abbr_day_names.each_with_index { |d, i| date_string = date_string.gsub(/#{d}/, english[i]) } when '%B' english = ::I18n.t('date.month_names', locale: :en)[1..-1] month_names.each_with_index { |m, i| date_string = date_string.gsub(/#{m}/, english[i]) } when '%b' english = ::I18n.t('date.abbr_month_names', locale: :en)[1..-1] abbr_month_names.each_with_index { |m, i| date_string = date_string.gsub(/#{m}/, english[i]) } when '%p' date_string = date_string.gsub(/#{::I18n.t('date.time.am', default: "am")}/, 'am') date_string = date_string.gsub(/#{::I18n.t('date.time.pm', default: "pm")}/, 'pm') end end date_string end def normalize(date_string, format) return unless date_string delocalize(date_string, format) parse_date_string(date_string) end # Parse normalized date strings using time zone def parse_date_string(date_string) ::Time.zone.parse(date_string) end end attr_reader :strftime_format def initialize(strftime_format) @strftime_format = strftime_format end # Ruby to javascript formatting options translator def to_momentjs strftime_format.gsub(/\w[^.(!?%)\W]{1,}/, '[\0]').gsub(/%(\w|\-\w)/) do |match| MOMENTJS_TRANSLATIONS[match] end end # Delocalize a l10n datetime strings def delocalize(value) self.class.delocalize(value, strftime_format) end def parse_string(value) return if value.blank? return value if %w(DateTime Date Time).include?(value.class.name) return if (delocalized_value = delocalize(value)).blank? begin # Adjust with the correct timezone and daylight savint time datetime_with_wrong_tz = ::DateTime.strptime(delocalized_value, strftime_format) Time.zone.parse(datetime_with_wrong_tz.strftime('%Y-%m-%d %H:%M:%S')) rescue ArgumentError nil end end end end end