class Stamp::Translator

Constants

ABBR_DAYNAMES_REGEXP
ABBR_MONTHNAMES_REGEXP
DAYNAMES_REGEXP
FOUR_DIGIT_REGEXP
HOUR_TO_12_HOUR
MERIDIAN_LOWER_REGEXP
MERIDIAN_UPPER_REGEXP
MONTHNAMES_REGEXP
OBVIOUS_24_HOUR

Disambiguate based on value

OBVIOUS_DAY
OBVIOUS_YEAR
ONE_DIGIT_REGEXP
ORDINAL_DAY_REGEXP
TIMEZONE_REGEXP
TIME_REGEXP
TIME_ZONE_ABBREVIATIONS

Full list of time zone abbreviations from en.wikipedia.org/wiki/List_of_time_zone_abbreviations

TWO_DIGIT_DAY_EMITTER
TWO_DIGIT_MONTH_EMITTER
TWO_DIGIT_REGEXP
TWO_DIGIT_YEAR_EMITTER

Public Instance Methods

build_emitters(tokens) { |token| ... } click to toggle source

Transforms tokens that look like date/time parts to emitter objects.

# File lib/stamp/translator.rb, line 70
def build_emitters(tokens)
  tokens.map do |token|
    yield(token) || Emitters::String.new(token)
  end
end
date_emitter(token) click to toggle source
# File lib/stamp/translator.rb, line 107
def date_emitter(token)
  case token
  when MONTHNAMES_REGEXP
    Emitters::Lookup.new(:month, Date::MONTHNAMES)

  when ABBR_MONTHNAMES_REGEXP
    Emitters::Lookup.new(:month, Date::ABBR_MONTHNAMES)

  when DAYNAMES_REGEXP
    Emitters::Lookup.new(:wday, Date::DAYNAMES)

  when ABBR_DAYNAMES_REGEXP
    Emitters::Lookup.new(:wday, Date::ABBR_DAYNAMES)

  when TIMEZONE_REGEXP
    Emitters::Delegate.new(:zone)

  when FOUR_DIGIT_REGEXP
    Emitters::Delegate.new(:year)

  when ORDINAL_DAY_REGEXP
    Emitters::Ordinal.new(:day)

  when TWO_DIGIT_REGEXP
    value = token.to_i

    case value
    when OBVIOUS_DAY
      TWO_DIGIT_DAY_EMITTER
    when OBVIOUS_YEAR
      TWO_DIGIT_YEAR_EMITTER
    else
      Emitters::Ambiguous.new(
        TWO_DIGIT_MONTH_EMITTER,
        TWO_DIGIT_DAY_EMITTER,
        TWO_DIGIT_YEAR_EMITTER)
    end

  when ONE_DIGIT_REGEXP
    Emitters::Ambiguous.new(
      Emitters::Delegate.new(:month),
      Emitters::Delegate.new(:day))
  end
end
time_emitter(token) click to toggle source
# File lib/stamp/translator.rb, line 76
def time_emitter(token)
  case token
  when MERIDIAN_LOWER_REGEXP
    Emitters::AmPm.new

  when MERIDIAN_UPPER_REGEXP
    Emitters::AmPm.new { |v| v.upcase }

  when TWO_DIGIT_REGEXP
    Emitters::Ambiguous.new(
      two_digit_hour_emitter(token),
      Emitters::TwoDigit.new(:min),
      Emitters::TwoDigit.new(:sec))

  when ONE_DIGIT_REGEXP
    # 12-hour clock without leading zero
    Emitters::Delegate.new(:hour, &HOUR_TO_12_HOUR)
  end
end
translate(example) click to toggle source
# File lib/stamp/translator.rb, line 46
def translate(example)
  # extract any substrings that look like times, like "23:59" or "8:37 am"
  before, time_example, after = example.partition(TIME_REGEXP)

  # build emitters from the example date
  emitters = Emitters::Composite.new
  emitters << build_emitters(before.split(/\b/)) do |token|
    date_emitter(token)
  end

  # build emitters from the example time
  unless time_example.empty?
    time_parts = time_example.scan(TIME_REGEXP).first
    emitters << build_emitters(time_parts) do |token|
      time_emitter(token)
    end
  end

  # recursively process any remaining text
  emitters << translate(after) unless after.empty?
  emitters
end
two_digit_hour_emitter(token) click to toggle source
# File lib/stamp/translator.rb, line 96
def two_digit_hour_emitter(token)
  case token.to_i
  when OBVIOUS_24_HOUR
    # 24-hour clock
    Emitters::TwoDigit.new(:hour)
  else
    # 12-hour clock with leading zero
    Emitters::TwoDigit.new(:hour, &HOUR_TO_12_HOUR)
  end
end