Class: Stamp::Translator
- Inherits:
-
Object
- Object
- Stamp::Translator
- Defined in:
- lib/stamp/translator.rb
Constant Summary collapse
- TIME_ZONE_ABBREVIATIONS =
Full list of time zone abbreviations from http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
%w{ ACDT ACST ACT ADT AEDT AEST AFT AKDT AKST AMST AMT ART AST AWDT AWST AZOST AZT BDT BIOT BIT BOT BRT BST BTT CAT CCT CDT CEDT CEST CET CHADT CHAST CHOT ChST CHUT CIST CIT CKT CLST CLT COST COT CST CT CVT CWST CXT DAVT DDUT DFT EASST EAST EAT ECT EDT EEDT EEST EET EGST EGT EIT EST FET FJT FKST FKT FNT GALT GAMT GET GFT GILT GIT GMT GST GYT HADT HAEC HAST HKT HMT HOVT HST ICT IDT IOT IRDT IRKT IRST IST JST KGT KOST KRAT KST LHST LINT MAGT MART MAWT MDT MET MEST MHT MIST MIT MMT MSK MST MUT MVT MYT NCT NDT NFT NPT NST NT NUT NZDT NZST OMST ORAT PDT PET PETT PGT PHOT PHT PKT PMDT PMST PONT PST RET ROTT SAKT SAMT SAST SBT SCT SGT SLT SRT SST SYOT TAHT THA TFT TJT TKT TLT TMT TOT TVT UCT ULAT UTC UYST UYT UZT VET VLAT VOLT VOST VUT WAKT WAST WAT WEDT WEST WET WST YAKT YEKT }
- TIMEZONE_REGEXP =
/^(#{TIME_ZONE_ABBREVIATIONS.join('|')})$/- MONTHNAMES_REGEXP =
/^(#{Date::MONTHNAMES.compact.join('|')})$/i- ABBR_MONTHNAMES_REGEXP =
/^(#{Date::ABBR_MONTHNAMES.compact.join('|')})$/i- DAYNAMES_REGEXP =
/^(#{Date::DAYNAMES.join('|')})$/i- ABBR_DAYNAMES_REGEXP =
/^(#{Date::ABBR_DAYNAMES.join('|')})$/i- ONE_DIGIT_REGEXP =
/^\d{1}$/- TWO_DIGIT_REGEXP =
/^\d{2}$/- FOUR_DIGIT_REGEXP =
/^\d{4}$/- TIME_REGEXP =
/(\d{1,2})(:)(\d{2})(\s*)(:)?(\d{2})?(\s*)?([ap]m)?/i- UTC_OFFSET_REGEXP =
UTC offsets like "+05:00" or "-0500". The lookbehind/lookahead keep date fragments like "12-31-1999" from matching; hours are capped at 14.
/(?<![-\d])[+-](?:0\d|1[0-4]):?[0-5]\d(?!\d)/- MERIDIAN_LOWER_REGEXP =
/^(a|p)m$/- MERIDIAN_UPPER_REGEXP =
/^(A|P)M$/- ORDINAL_DAY_REGEXP =
/^(\d{1,2})(st|nd|rd|th)$/- OBVIOUS_24_HOUR =
Disambiguate based on value
13..23
- OBVIOUS_DAY =
13..31
- OBVIOUS_YEAR =
32..99
Instance Method Summary collapse
-
#build_emitters(tokens) ⇒ Object
Transforms tokens that look like date/time parts to emitter objects.
- #date_emitter(token) ⇒ Object
- #time_emitter(token) ⇒ Object
- #translate(example) ⇒ Object
- #two_digit_hour_emitter(token) ⇒ Object
Instance Method Details
#build_emitters(tokens) ⇒ Object
Transforms tokens that look like date/time parts to emitter objects.
80 81 82 83 84 |
# File 'lib/stamp/translator.rb', line 80 def build_emitters(tokens) tokens.map do |token| yield(token) || Emitters::String.new(token) end end |
#date_emitter(token) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/stamp/translator.rb', line 117 def date_emitter(token) case token when MONTHNAMES_REGEXP Emitters::Lookup::MONTH when ABBR_MONTHNAMES_REGEXP Emitters::Lookup::ABBR_MONTH when DAYNAMES_REGEXP Emitters::Lookup::DAY when ABBR_DAYNAMES_REGEXP Emitters::Lookup::ABBR_DAY when TIMEZONE_REGEXP Emitters::Delegate::ZONE when FOUR_DIGIT_REGEXP Emitters::Delegate::YEAR when ORDINAL_DAY_REGEXP Emitters::Ordinal::DAY when TWO_DIGIT_REGEXP case token.to_i when OBVIOUS_DAY Emitters::TwoDigit::DAY when OBVIOUS_YEAR Emitters::TwoDigit::YEAR else Emitters::Ambiguous.new( Emitters::TwoDigit::MONTH, Emitters::TwoDigit::DAY, Emitters::TwoDigit::YEAR) end when ONE_DIGIT_REGEXP Emitters::Ambiguous.new( Emitters::Delegate::MONTH, Emitters::Delegate::DAY) end end |
#time_emitter(token) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/stamp/translator.rb', line 86 def time_emitter(token) case token when MERIDIAN_LOWER_REGEXP Emitters::AmPm::LOWERCASE when MERIDIAN_UPPER_REGEXP Emitters::AmPm::UPPERCASE when TWO_DIGIT_REGEXP Emitters::Ambiguous.new( two_digit_hour_emitter(token), Emitters::TwoDigit::MIN, Emitters::TwoDigit::SEC) when ONE_DIGIT_REGEXP # 12-hour clock without leading zero Emitters::TwelveHour::NON_LEADING_ZERO end end |
#translate(example) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/stamp/translator.rb', line 45 def translate(example) # extract any substrings that look like UTC offsets, like "+05:00" or # "-0500", before the time logic can mistake them for clock times before, offset_example, after = example.partition(UTC_OFFSET_REGEXP) unless offset_example.empty? emitters = Emitters::Composite.new emitters << translate(before) unless before.empty? emitters << (offset_example.include?(":") ? Emitters::UtcOffset::COLON : Emitters::UtcOffset::PLAIN) emitters << translate(after) unless after.empty? return emitters end # 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) ⇒ Object
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/stamp/translator.rb', line 106 def two_digit_hour_emitter(token) case token.to_i when OBVIOUS_24_HOUR # 24-hour clock Emitters::TwoDigit::HOUR else # 12-hour clock with leading zero Emitters::TwelveHour::LEADING_ZERO end end |