class Delocalize::Parsers::DateTime

Constants

REGEXPS

extend/change this according to your needs by merging your custom regexps

Attributes

type[R]

Public Class Methods

new(type) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 27
def initialize(type)
  @type = type
end

Public Instance Methods

parse(datetime) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 31
def parse(datetime)
  return unless datetime
  return datetime if datetime.respond_to?(:strftime) # already a Date/Time object -> no need to parse it

  translate_month_and_day_names(datetime)
  input_formats(type).each do |original_format|
    next unless datetime =~ /^#{apply_regex(original_format)}$/

    datetime = ::DateTime.strptime(datetime, original_format) rescue break
    return Date == type ?
      datetime.to_date :
      Time.zone.local(datetime.year, datetime.mon, datetime.mday, datetime.hour, datetime.min, datetime.sec)
  end
  default_parse(datetime, type)
end

Private Instance Methods

apply_regex(format) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 84
def apply_regex(format)
  format.gsub(/(#{REGEXPS.keys.join('|')})/) { |s| REGEXPS[$1] }
end
default_parse(datetime, type) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 49
def default_parse(datetime, type)
  return if datetime.blank?

  today = Date.current
  parsed = Date._parse(datetime)
  raise ArgumentError, "invalid date: #{datetime}" if parsed.empty? # the datetime value is invalid

  # set default year, month and day if not found
  parsed.reverse_merge!(:year => today.year, :mon => today.mon, :mday => today.mday)

  if Date == type
    Date.civil(*parsed.values_at(:year, :mon, :mday))
  else
    Time.zone.local(*parsed.values_at(:year, :mon, :mday, :hour, :min, :sec))
  end
end
input_formats(type) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 78
def input_formats(type)
  # Date uses date formats, all others use time formats
  type = type == Date ? :date : :time
  I18n.t(:"#{type}.formats").slice(*I18n.t(:"#{type}.input.formats")).values
end
translate_month_and_day_names(datetime) click to toggle source
# File lib/delocalize/parsers/date_time.rb, line 66
def translate_month_and_day_names(datetime)
  # Note: This should be a bulk lookup but due to a bug in i18n it doesn't work properly with fallbacks.
  # See https://github.com/svenfuchs/i18n/issues/104.
  # TODO Make it a bulk lookup again at some point in the future when the bug is fixed in i18n.
  translated = [:month_names, :abbr_month_names, :day_names, :abbr_day_names].map do |key|
    I18n.t(key, :scope => :date)
  end.flatten.compact

  original = (Date::MONTHNAMES + Date::ABBR_MONTHNAMES + Date::DAYNAMES + Date::ABBR_DAYNAMES).compact
  translated.each_with_index { |name, i| datetime.gsub!(/\b#{name}\b/, original[i]) }
end