gitlab-chronic 0.10.4 → 0.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +0 -1
 - data/.travis.yml +4 -6
 - data/HISTORY.md +4 -0
 - data/README.md +7 -10
 - data/chronic.gemspec +1 -1
 - data/lib/chronic/date.rb +7 -6
 - data/lib/chronic/{tags/grabber.rb → grabber.rb} +10 -6
 - data/lib/chronic/handlers.rb +2 -27
 - data/lib/chronic/mini_date.rb +2 -2
 - data/lib/chronic/numerizer.rb +130 -0
 - data/lib/chronic/{tags/ordinal.rb → ordinal.rb} +8 -11
 - data/lib/chronic/parser.rb +80 -34
 - data/lib/chronic/{tags/pointer.rb → pointer.rb} +9 -5
 - data/lib/chronic/{tags/repeater.rb → repeater.rb} +11 -26
 - data/lib/chronic/repeaters/repeater_day.rb +1 -1
 - data/lib/chronic/repeaters/repeater_day_name.rb +2 -2
 - data/lib/chronic/repeaters/repeater_day_portion.rb +3 -3
 - data/lib/chronic/repeaters/repeater_fortnight.rb +1 -1
 - data/lib/chronic/repeaters/repeater_hour.rb +1 -1
 - data/lib/chronic/repeaters/repeater_minute.rb +1 -1
 - data/lib/chronic/repeaters/repeater_month.rb +1 -1
 - data/lib/chronic/repeaters/repeater_month_name.rb +2 -2
 - data/lib/chronic/repeaters/repeater_season.rb +1 -1
 - data/lib/chronic/repeaters/repeater_second.rb +1 -1
 - data/lib/chronic/repeaters/repeater_time.rb +2 -2
 - data/lib/chronic/repeaters/repeater_week.rb +22 -23
 - data/lib/chronic/repeaters/repeater_weekday.rb +2 -2
 - data/lib/chronic/repeaters/repeater_weekend.rb +1 -1
 - data/lib/chronic/repeaters/repeater_year.rb +1 -1
 - data/lib/chronic/{tags/scalar.rb → scalar.rb} +10 -18
 - data/lib/chronic/separator.rb +207 -0
 - data/lib/chronic/{tags/sign.rb → sign.rb} +16 -2
 - data/lib/chronic/tag.rb +7 -59
 - data/lib/chronic/time.rb +8 -8
 - data/lib/chronic/{tags/time_zone.rb → time_zone.rb} +1 -1
 - data/lib/chronic/token.rb +3 -13
 - data/lib/chronic/version.rb +1 -1
 - data/lib/gitlab-chronic.rb +14 -18
 - data/test/test_chronic.rb +6 -26
 - data/test/test_handler.rb +1 -1
 - data/test/test_numerizer.rb +86 -0
 - data/test/test_parsing.rb +8 -306
 - data/test/test_repeater_week.rb +0 -53
 - data/test/test_token.rb +0 -6
 - metadata +13 -19
 - data/lib/chronic/definition.rb +0 -128
 - data/lib/chronic/dictionary.rb +0 -36
 - data/lib/chronic/repeaters/repeater_quarter.rb +0 -59
 - data/lib/chronic/repeaters/repeater_quarter_name.rb +0 -40
 - data/lib/chronic/tags/separator.rb +0 -123
 - data/lib/chronic/tokenizer.rb +0 -38
 - data/test/test_repeater_quarter.rb +0 -70
 - data/test/test_repeater_quarter_name.rb +0 -198
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2b5a569ed8fd73d35d0726a7cb2f19f1ca3507543032bff4ca3f1aa73e1ba94f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 15f9949677fc421bf44def4fbf0da85928847e4918d4375657cf43c64f3f92fe
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d8ae6e9b8292042fce47b1125f2fd11aab058e45c5ab00fe01fdee2e8b8dddcc062fd505f1de80bc7a05fcc04c329e3229746bcbfaaa07b5d3d82ad7161a1a09
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 727012bcb6c52dcd35e3f87ef099d50e27d7ab7b7c719a8f21d25e4ab802c06b3aa70a1acb790fa376efb2851d2c2d8e03c33539e3c03e51f33b90f04893044f
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    CHANGED
    
    
    
        data/HISTORY.md
    CHANGED
    
    | 
         @@ -1,5 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ## --- Begin gitlab-chronic changes ---
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            # 0.10.5 / 2019-11-25
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * Revert changes made between v0.10.2..master ((https://gitlab.com/gitlab-org/gitlab-chronic/merge_requests/7)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       3 
7 
     | 
    
         
             
            # 0.10.4 / 2019-11-24
         
     | 
| 
       4 
8 
     | 
    
         | 
| 
       5 
9 
     | 
    
         
             
            * Rename chronic -> gitlab-chronic (https://gitlab.com/gitlab-org/gitlab-chronic/merge_requests/5)
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -57,7 +57,7 @@ Chronic can parse a huge variety of date and time formats. Following is a 
     | 
|
| 
       57 
57 
     | 
    
         
             
            small sample of strings that will be properly parsed. Parsing is case
         
     | 
| 
       58 
58 
     | 
    
         
             
            insensitive and will handle common abbreviations and misspellings.
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
      
 60 
     | 
    
         
            +
            Simple
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
62 
     | 
    
         
             
            * thursday
         
     | 
| 
       63 
63 
     | 
    
         
             
            * november
         
     | 
| 
         @@ -89,7 +89,7 @@ insensitive and will handle common abbreviations and misspellings. 
     | 
|
| 
       89 
89 
     | 
    
         
             
            * afternoon yesterday
         
     | 
| 
       90 
90 
     | 
    
         
             
            * thursday last week
         
     | 
| 
       91 
91 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
      
 92 
     | 
    
         
            +
            Complex
         
     | 
| 
       93 
93 
     | 
    
         | 
| 
       94 
94 
     | 
    
         
             
            * 3 years ago
         
     | 
| 
       95 
95 
     | 
    
         
             
            * a year ago
         
     | 
| 
         @@ -108,7 +108,7 @@ insensitive and will handle common abbreviations and misspellings. 
     | 
|
| 
       108 
108 
     | 
    
         
             
            * fourteenth of june 2010 at eleven o'clock in the evening
         
     | 
| 
       109 
109 
     | 
    
         
             
            * may seventh '97 at three in the morning
         
     | 
| 
       110 
110 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
      
 111 
     | 
    
         
            +
            Specific Dates
         
     | 
| 
       112 
112 
     | 
    
         | 
| 
       113 
113 
     | 
    
         
             
            * January 5
         
     | 
| 
       114 
114 
     | 
    
         
             
            * 22nd of june
         
     | 
| 
         @@ -133,14 +133,12 @@ insensitive and will handle common abbreviations and misspellings. 
     | 
|
| 
       133 
133 
     | 
    
         
             
            * 17:00
         
     | 
| 
       134 
134 
     | 
    
         
             
            * 0800
         
     | 
| 
       135 
135 
     | 
    
         | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
      
 136 
     | 
    
         
            +
            Specific Times (many of the above with an added time)
         
     | 
| 
       137 
137 
     | 
    
         | 
| 
       138 
138 
     | 
    
         
             
            * January 5 at 7pm
         
     | 
| 
       139 
139 
     | 
    
         
             
            * 22nd of june at 8am
         
     | 
| 
       140 
140 
     | 
    
         
             
            * 1979-05-27 05:00:00
         
     | 
| 
       141 
141 
     | 
    
         
             
            * 03/01/2012 07:25:09.234567
         
     | 
| 
       142 
     | 
    
         
            -
            * 2013-08-01T19:30:00.345-07:00
         
     | 
| 
       143 
     | 
    
         
            -
            * 2013-08-01T19:30:00.34-07:00
         
     | 
| 
       144 
142 
     | 
    
         
             
            * etc
         
     | 
| 
       145 
143 
     | 
    
         | 
| 
       146 
144 
     | 
    
         | 
| 
         @@ -163,7 +161,7 @@ class to get full time zone support. 
     | 
|
| 
       163 
161 
     | 
    
         | 
| 
       164 
162 
     | 
    
         
             
            Chronic uses Ruby's built in Time class for all time storage and computation.
         
     | 
| 
       165 
163 
     | 
    
         
             
            Because of this, only times that the Time class can handle will be properly
         
     | 
| 
       166 
     | 
    
         
            -
            parsed. Parsing for times outside of this range will simply return  
     | 
| 
      
 164 
     | 
    
         
            +
            parsed. Parsing for times outside of this range will simply return nil.
         
     | 
| 
       167 
165 
     | 
    
         
             
            Support for a wider range of times is planned for a future release.
         
     | 
| 
       168 
166 
     | 
    
         | 
| 
       169 
167 
     | 
    
         | 
| 
         @@ -177,10 +175,9 @@ The best way to get your changes merged back into core is as follows: 
     | 
|
| 
       177 
175 
     | 
    
         | 
| 
       178 
176 
     | 
    
         
             
            1. Clone down your fork
         
     | 
| 
       179 
177 
     | 
    
         
             
            1. Create a thoughtfully named topic branch to contain your change
         
     | 
| 
       180 
     | 
    
         
            -
            1. Install the development dependencies by running `bundle install`
         
     | 
| 
       181 
178 
     | 
    
         
             
            1. Hack away
         
     | 
| 
       182 
     | 
    
         
            -
            1. Add tests and make sure everything still passes by running ` 
     | 
| 
       183 
     | 
    
         
            -
            1. Ensure your tests pass in multiple timezones. ie `TZ=utc  
     | 
| 
      
 179 
     | 
    
         
            +
            1. Add tests and make sure everything still passes by running `rake`
         
     | 
| 
      
 180 
     | 
    
         
            +
            1. Ensure your tests pass in multiple timezones. ie `TZ=utc rake` `TZ=BST rake`
         
     | 
| 
       184 
181 
     | 
    
         
             
            1. If you are adding new functionality, document it in the README
         
     | 
| 
       185 
182 
     | 
    
         
             
            1. Do not change the version number, we will do that on our end
         
     | 
| 
       186 
183 
     | 
    
         
             
            1. If necessary, rebase your commits into logical chunks, without errors
         
     | 
    
        data/chronic.gemspec
    CHANGED
    
    
    
        data/lib/chronic/date.rb
    CHANGED
    
    | 
         @@ -35,19 +35,20 @@ module Chronic 
     | 
|
| 
       35 
35 
     | 
    
         
             
                }
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                # Checks if given number could be day
         
     | 
| 
       38 
     | 
    
         
            -
                def self.could_be_day?(day 
     | 
| 
       39 
     | 
    
         
            -
                  day >= 1 && day <= 31 
     | 
| 
      
 38 
     | 
    
         
            +
                def self.could_be_day?(day)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  day >= 1 && day <= 31
         
     | 
| 
       40 
40 
     | 
    
         
             
                end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
                # Checks if given number could be month
         
     | 
| 
       43 
     | 
    
         
            -
                def self.could_be_month?(month 
     | 
| 
       44 
     | 
    
         
            -
                  month >= 1 && month <= 12 
     | 
| 
      
 43 
     | 
    
         
            +
                def self.could_be_month?(month)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  month >= 1 && month <= 12
         
     | 
| 
       45 
45 
     | 
    
         
             
                end
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
       47 
47 
     | 
    
         
             
                # Checks if given number could be year
         
     | 
| 
       48 
     | 
    
         
            -
                def self.could_be_year?(year 
     | 
| 
       49 
     | 
    
         
            -
                  year >=  
     | 
| 
      
 48 
     | 
    
         
            +
                def self.could_be_year?(year)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  year >= 1 && year <= 9999
         
     | 
| 
       50 
50 
     | 
    
         
             
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       51 
52 
     | 
    
         
             
                # Build a year from a 2 digit suffix.
         
     | 
| 
       52 
53 
     | 
    
         
             
                #
         
     | 
| 
       53 
54 
     | 
    
         
             
                # year - The two digit Integer year to build from.
         
     | 
| 
         @@ -10,15 +10,19 @@ module Chronic 
     | 
|
| 
       10 
10 
     | 
    
         
             
                # Returns an Array of Token objects.
         
     | 
| 
       11 
11 
     | 
    
         
             
                def self.scan(tokens, options)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  tokens.each do |token|
         
     | 
| 
       13 
     | 
    
         
            -
                    token.tag 
     | 
| 
      
 13 
     | 
    
         
            +
                    if t = scan_for_all(token) then token.tag(t); next end
         
     | 
| 
       14 
14 
     | 
    
         
             
                  end
         
     | 
| 
       15 
15 
     | 
    
         
             
                end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                # token - The Token object to scan.
         
     | 
| 
      
 18 
     | 
    
         
            +
                #
         
     | 
| 
      
 19 
     | 
    
         
            +
                # Returns a new Grabber object.
         
     | 
| 
      
 20 
     | 
    
         
            +
                def self.scan_for_all(token)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  scan_for token, self,
         
     | 
| 
      
 22 
     | 
    
         
            +
                  {
         
     | 
| 
      
 23 
     | 
    
         
            +
                    /last/ => :last,
         
     | 
| 
      
 24 
     | 
    
         
            +
                    /this/ => :this,
         
     | 
| 
      
 25 
     | 
    
         
            +
                    /next/ => :next
         
     | 
| 
       22 
26 
     | 
    
         
             
                  }
         
     | 
| 
       23 
27 
     | 
    
         
             
                end
         
     | 
| 
       24 
28 
     | 
    
         | 
    
        data/lib/chronic/handlers.rb
    CHANGED
    
    | 
         @@ -8,7 +8,6 @@ module Chronic 
     | 
|
| 
       8 
8 
     | 
    
         
             
                  span = month.this(options[:context])
         
     | 
| 
       9 
9 
     | 
    
         
             
                  year, month = span.begin.year, span.begin.month
         
     | 
| 
       10 
10 
     | 
    
         
             
                  day_start = Chronic.time_class.local(year, month, day)
         
     | 
| 
       11 
     | 
    
         
            -
                  day_start = Chronic.time_class.local(year + 1, month, day) if options[:context] == :future && day_start < now
         
     | 
| 
       12 
11 
     | 
    
         | 
| 
       13 
12 
     | 
    
         
             
                  day_or_time(day_start, time_tokens, options)
         
     | 
| 
       14 
13 
     | 
    
         
             
                end
         
     | 
| 
         @@ -110,19 +109,6 @@ module Chronic 
     | 
|
| 
       110 
109 
     | 
    
         
             
                  handle_m_d(month, day, tokens[token_range], options)
         
     | 
| 
       111 
110 
     | 
    
         
             
                end
         
     | 
| 
       112 
111 
     | 
    
         | 
| 
       113 
     | 
    
         
            -
                # Handle scalar-year/repeater-quarter-name
         
     | 
| 
       114 
     | 
    
         
            -
                def handle_sy_rqn(tokens, options)
         
     | 
| 
       115 
     | 
    
         
            -
                  handle_rqn_sy(tokens[0..1].reverse, options)
         
     | 
| 
       116 
     | 
    
         
            -
                end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                # Handle repeater-quarter-name/scalar-year
         
     | 
| 
       119 
     | 
    
         
            -
                def handle_rqn_sy(tokens, options)
         
     | 
| 
       120 
     | 
    
         
            -
                  year = tokens[1].get_tag(ScalarYear).type
         
     | 
| 
       121 
     | 
    
         
            -
                  quarter_tag = tokens[0].get_tag(RepeaterQuarterName)
         
     | 
| 
       122 
     | 
    
         
            -
                  quarter_tag.start = Chronic.construct(year)
         
     | 
| 
       123 
     | 
    
         
            -
                  quarter_tag.this(:none)
         
     | 
| 
       124 
     | 
    
         
            -
                end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
112 
     | 
    
         
             
                # Handle repeater-month-name/scalar-year
         
     | 
| 
       127 
113 
     | 
    
         
             
                def handle_rmn_sy(tokens, options)
         
     | 
| 
       128 
114 
     | 
    
         
             
                  month = tokens[0].get_tag(RepeaterMonthName).index
         
     | 
| 
         @@ -252,13 +238,7 @@ module Chronic 
     | 
|
| 
       252 
238 
     | 
    
         | 
| 
       253 
239 
     | 
    
         
             
                  begin
         
     | 
| 
       254 
240 
     | 
    
         
             
                    day_start = Chronic.time_class.local(year, month, day)
         
     | 
| 
       255 
     | 
    
         
            -
             
     | 
| 
       256 
     | 
    
         
            -
                    if options[:context] == :future && day_start < now
         
     | 
| 
       257 
     | 
    
         
            -
                      day_start = Chronic.time_class.local(year + 1, month, day)
         
     | 
| 
       258 
     | 
    
         
            -
                    elsif options[:context] == :past && day_start > now
         
     | 
| 
       259 
     | 
    
         
            -
                      day_start = Chronic.time_class.local(year - 1, month, day)
         
     | 
| 
       260 
     | 
    
         
            -
                    end
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
      
 241 
     | 
    
         
            +
                    day_start = Chronic.time_class.local(year + 1, month, day) if options[:context] == :future && day_start < now
         
     | 
| 
       262 
242 
     | 
    
         
             
                    day_or_time(day_start, time_tokens, options)
         
     | 
| 
       263 
243 
     | 
    
         
             
                  rescue ArgumentError
         
     | 
| 
       264 
244 
     | 
    
         
             
                    nil
         
     | 
| 
         @@ -470,11 +450,6 @@ module Chronic 
     | 
|
| 
       470 
450 
     | 
    
         
             
                  handle_srp(tokens, anchor_span, options)
         
     | 
| 
       471 
451 
     | 
    
         
             
                end
         
     | 
| 
       472 
452 
     | 
    
         | 
| 
       473 
     | 
    
         
            -
                # Handle repeater/scalar/repeater/pointer
         
     | 
| 
       474 
     | 
    
         
            -
                def handle_rmn_s_r_p(tokens, options)
         
     | 
| 
       475 
     | 
    
         
            -
                  handle_s_r_p_a(tokens[1..3] + tokens[0..0], options)
         
     | 
| 
       476 
     | 
    
         
            -
                end
         
     | 
| 
       477 
     | 
    
         
            -
             
     | 
| 
       478 
453 
     | 
    
         
             
                def handle_s_r_a_s_r_p_a(tokens, options)
         
     | 
| 
       479 
454 
     | 
    
         
             
                  anchor_span = get_anchor(tokens[4..tokens.size - 1], options)
         
     | 
| 
       480 
455 
     | 
    
         | 
| 
         @@ -553,7 +528,7 @@ module Chronic 
     | 
|
| 
       553 
528 
     | 
    
         
             
                  when :next
         
     | 
| 
       554 
529 
     | 
    
         
             
                    outer_span = head.next(:future)
         
     | 
| 
       555 
530 
     | 
    
         
             
                  else
         
     | 
| 
       556 
     | 
    
         
            -
                    raise  
     | 
| 
      
 531 
     | 
    
         
            +
                    raise "Invalid grabber"
         
     | 
| 
       557 
532 
     | 
    
         
             
                  end
         
     | 
| 
       558 
533 
     | 
    
         | 
| 
       559 
534 
     | 
    
         
             
                  if Chronic.debug
         
     | 
    
        data/lib/chronic/mini_date.rb
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ module Chronic 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                def initialize(month, day)
         
     | 
| 
       10 
10 
     | 
    
         
             
                  unless (1..12).include?(month)
         
     | 
| 
       11 
     | 
    
         
            -
                    raise ArgumentError,  
     | 
| 
      
 11 
     | 
    
         
            +
                    raise ArgumentError, "1..12 are valid months"
         
     | 
| 
       12 
12 
     | 
    
         
             
                  end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                  @month = month
         
     | 
| 
         @@ -35,4 +35,4 @@ module Chronic 
     | 
|
| 
       35 
35 
     | 
    
         
             
                  @month == other.month and @day == other.day
         
     | 
| 
       36 
36 
     | 
    
         
             
                end
         
     | 
| 
       37 
37 
     | 
    
         
             
              end
         
     | 
| 
       38 
     | 
    
         
            -
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,130 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'strscan'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Chronic
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Numerizer
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                DIRECT_NUMS = [
         
     | 
| 
      
 7 
     | 
    
         
            +
                  ['eleven', '11'],
         
     | 
| 
      
 8 
     | 
    
         
            +
                  ['twelve', '12'],
         
     | 
| 
      
 9 
     | 
    
         
            +
                  ['thirteen', '13'],
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ['fourteen', '14'],
         
     | 
| 
      
 11 
     | 
    
         
            +
                  ['fifteen', '15'],
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ['sixteen', '16'],
         
     | 
| 
      
 13 
     | 
    
         
            +
                  ['seventeen', '17'],
         
     | 
| 
      
 14 
     | 
    
         
            +
                  ['eighteen', '18'],
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ['nineteen', '19'],
         
     | 
| 
      
 16 
     | 
    
         
            +
                  ['ninteen', '19'], # Common mis-spelling
         
     | 
| 
      
 17 
     | 
    
         
            +
                  ['zero', '0'],
         
     | 
| 
      
 18 
     | 
    
         
            +
                  ['one', '1'],
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ['two', '2'],
         
     | 
| 
      
 20 
     | 
    
         
            +
                  ['three', '3'],
         
     | 
| 
      
 21 
     | 
    
         
            +
                  ['four(\W|$)', '4\1'],  # The weird regex is so that it matches four but not fourty
         
     | 
| 
      
 22 
     | 
    
         
            +
                  ['five', '5'],
         
     | 
| 
      
 23 
     | 
    
         
            +
                  ['six(\W|$)', '6\1'],
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ['seven(\W|$)', '7\1'],
         
     | 
| 
      
 25 
     | 
    
         
            +
                  ['eight(\W|$)', '8\1'],
         
     | 
| 
      
 26 
     | 
    
         
            +
                  ['nine(\W|$)', '9\1'],
         
     | 
| 
      
 27 
     | 
    
         
            +
                  ['ten', '10'],
         
     | 
| 
      
 28 
     | 
    
         
            +
                  ['\ba[\b^$]', '1'] # doesn't make sense for an 'a' at the end to be a 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                ]
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                ORDINALS = [
         
     | 
| 
      
 32 
     | 
    
         
            +
                  ['first', '1'],
         
     | 
| 
      
 33 
     | 
    
         
            +
                  ['third', '3'],
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ['fourth', '4'],
         
     | 
| 
      
 35 
     | 
    
         
            +
                  ['fifth', '5'],
         
     | 
| 
      
 36 
     | 
    
         
            +
                  ['sixth', '6'],
         
     | 
| 
      
 37 
     | 
    
         
            +
                  ['seventh', '7'],
         
     | 
| 
      
 38 
     | 
    
         
            +
                  ['eighth', '8'],
         
     | 
| 
      
 39 
     | 
    
         
            +
                  ['ninth', '9'],
         
     | 
| 
      
 40 
     | 
    
         
            +
                  ['tenth', '10'],
         
     | 
| 
      
 41 
     | 
    
         
            +
                  ['twelfth', '12'],
         
     | 
| 
      
 42 
     | 
    
         
            +
                  ['twentieth', '20'],
         
     | 
| 
      
 43 
     | 
    
         
            +
                  ['thirtieth', '30'],
         
     | 
| 
      
 44 
     | 
    
         
            +
                  ['fourtieth', '40'],
         
     | 
| 
      
 45 
     | 
    
         
            +
                  ['fiftieth', '50'],
         
     | 
| 
      
 46 
     | 
    
         
            +
                  ['sixtieth', '60'],
         
     | 
| 
      
 47 
     | 
    
         
            +
                  ['seventieth', '70'],
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ['eightieth', '80'],
         
     | 
| 
      
 49 
     | 
    
         
            +
                  ['ninetieth', '90']
         
     | 
| 
      
 50 
     | 
    
         
            +
                ]
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                TEN_PREFIXES = [
         
     | 
| 
      
 53 
     | 
    
         
            +
                  ['twenty', 20],
         
     | 
| 
      
 54 
     | 
    
         
            +
                  ['thirty', 30],
         
     | 
| 
      
 55 
     | 
    
         
            +
                  ['forty', 40],
         
     | 
| 
      
 56 
     | 
    
         
            +
                  ['fourty', 40], # Common mis-spelling
         
     | 
| 
      
 57 
     | 
    
         
            +
                  ['fifty', 50],
         
     | 
| 
      
 58 
     | 
    
         
            +
                  ['sixty', 60],
         
     | 
| 
      
 59 
     | 
    
         
            +
                  ['seventy', 70],
         
     | 
| 
      
 60 
     | 
    
         
            +
                  ['eighty', 80],
         
     | 
| 
      
 61 
     | 
    
         
            +
                  ['ninety', 90]
         
     | 
| 
      
 62 
     | 
    
         
            +
                ]
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                BIG_PREFIXES = [
         
     | 
| 
      
 65 
     | 
    
         
            +
                  ['hundred', 100],
         
     | 
| 
      
 66 
     | 
    
         
            +
                  ['thousand', 1000],
         
     | 
| 
      
 67 
     | 
    
         
            +
                  ['million', 1_000_000],
         
     | 
| 
      
 68 
     | 
    
         
            +
                  ['billion', 1_000_000_000],
         
     | 
| 
      
 69 
     | 
    
         
            +
                  ['trillion', 1_000_000_000_000],
         
     | 
| 
      
 70 
     | 
    
         
            +
                ]
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def self.numerize(string)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  string = string.dup
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  # preprocess
         
     | 
| 
      
 76 
     | 
    
         
            +
                  string.gsub!(/ +|([^\d])-([^\d])/, '\1 \2') # will mutilate hyphenated-words but shouldn't matter for date extraction
         
     | 
| 
      
 77 
     | 
    
         
            +
                  string.gsub!(/a half/, 'haAlf') # take the 'a' out so it doesn't turn into a 1, save the half for the end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # easy/direct replacements
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  DIRECT_NUMS.each do |dn|
         
     | 
| 
      
 82 
     | 
    
         
            +
                    string.gsub!(/#{dn[0]}/i, '<num>' + dn[1])
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  ORDINALS.each do |on|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    string.gsub!(/#{on[0]}/i, '<num>' + on[1] + on[0][-2, 2])
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  # ten, twenty, etc.
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  TEN_PREFIXES.each do |tp|
         
     | 
| 
      
 92 
     | 
    
         
            +
                    string.gsub!(/(?:#{tp[0]}) *<num>(\d(?=[^\d]|$))*/i) { '<num>' + (tp[1] + $1.to_i).to_s }
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  TEN_PREFIXES.each do |tp|
         
     | 
| 
      
 96 
     | 
    
         
            +
                    string.gsub!(/#{tp[0]}/i) { '<num>' + tp[1].to_s }
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  # hundreds, thousands, millions, etc.
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  BIG_PREFIXES.each do |bp|
         
     | 
| 
      
 102 
     | 
    
         
            +
                    string.gsub!(/(?:<num>)?(\d*) *#{bp[0]}/i) { $1.empty? ? bp[1] : '<num>' + (bp[1] * $1.to_i).to_s}
         
     | 
| 
      
 103 
     | 
    
         
            +
                    andition(string)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  # fractional addition
         
     | 
| 
      
 107 
     | 
    
         
            +
                  # I'm not combining this with the previous block as using float addition complicates the strings
         
     | 
| 
      
 108 
     | 
    
         
            +
                  # (with extraneous .0's and such )
         
     | 
| 
      
 109 
     | 
    
         
            +
                  string.gsub!(/(\d+)(?: | and |-)*haAlf/i) { ($1.to_f + 0.5).to_s }
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  string.gsub(/<num>/, '')
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 115 
     | 
    
         
            +
                  private
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  def andition(string)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    sc = StringScanner.new(string)
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                    while sc.scan_until(/<num>(\d+)( | and )<num>(\d+)(?=[^\w]|$)/i)
         
     | 
| 
      
 121 
     | 
    
         
            +
                      if sc[2] =~ /and/ || sc[1].size > sc[3].size
         
     | 
| 
      
 122 
     | 
    
         
            +
                        string[(sc.pos - sc.matched_size)..(sc.pos-1)] = '<num>' + (sc[1].to_i + sc[3].to_i).to_s
         
     | 
| 
      
 123 
     | 
    
         
            +
                        sc.reset
         
     | 
| 
      
 124 
     | 
    
         
            +
                      end
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -11,17 +11,14 @@ module Chronic 
     | 
|
| 
       11 
11 
     | 
    
         
             
                def self.scan(tokens, options)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  tokens.each_index do |i|
         
     | 
| 
       13 
13 
     | 
    
         
             
                    if tokens[i].word =~ /^(\d+)(st|nd|rd|th|\.)$/
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                         
     | 
| 
       22 
     | 
    
         
            -
                      end
         
     | 
| 
       23 
     | 
    
         
            -
                    elsif tokens[i].word =~ /^second$/
         
     | 
| 
       24 
     | 
    
         
            -
                      tokens[i].tag(Ordinal.new(2, 1))
         
     | 
| 
      
 14 
     | 
    
         
            +
                        ordinal = $1.to_i
         
     | 
| 
      
 15 
     | 
    
         
            +
                        tokens[i].tag(Ordinal.new(ordinal))
         
     | 
| 
      
 16 
     | 
    
         
            +
                        tokens[i].tag(OrdinalDay.new(ordinal)) if Chronic::Date::could_be_day?(ordinal)
         
     | 
| 
      
 17 
     | 
    
         
            +
                        tokens[i].tag(OrdinalMonth.new(ordinal)) if Chronic::Date::could_be_month?(ordinal)
         
     | 
| 
      
 18 
     | 
    
         
            +
                        if Chronic::Date::could_be_year?(ordinal)
         
     | 
| 
      
 19 
     | 
    
         
            +
                            year = Chronic::Date::make_year(ordinal, options[:ambiguous_year_future_bias])
         
     | 
| 
      
 20 
     | 
    
         
            +
                            tokens[i].tag(OrdinalYear.new(year.to_i))
         
     | 
| 
      
 21 
     | 
    
         
            +
                        end
         
     | 
| 
       25 
22 
     | 
    
         
             
                    end
         
     | 
| 
       26 
23 
     | 
    
         
             
                  end
         
     | 
| 
       27 
24 
     | 
    
         
             
                end
         
     | 
    
        data/lib/chronic/parser.rb
    CHANGED
    
    | 
         @@ -1,4 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'chronic/dictionary'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'chronic/handlers'
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            module Chronic
         
     | 
| 
         @@ -10,7 +9,6 @@ module Chronic 
     | 
|
| 
       10 
9 
     | 
    
         
             
                  :context => :future,
         
     | 
| 
       11 
10 
     | 
    
         
             
                  :now => nil,
         
     | 
| 
       12 
11 
     | 
    
         
             
                  :hours24 => nil,
         
     | 
| 
       13 
     | 
    
         
            -
                  :week_start => :sunday,
         
     | 
| 
       14 
12 
     | 
    
         
             
                  :guess => true,
         
     | 
| 
       15 
13 
     | 
    
         
             
                  :ambiguous_time_range => 6,
         
     | 
| 
       16 
14 
     | 
    
         
             
                  :endian_precedence    => [:middle, :little],
         
     | 
| 
         @@ -27,9 +25,6 @@ module Chronic 
     | 
|
| 
       27 
25 
     | 
    
         
             
                #        :now - Time, all computations will be based off of time
         
     | 
| 
       28 
26 
     | 
    
         
             
                #               instead of Time.now.
         
     | 
| 
       29 
27 
     | 
    
         
             
                #        :hours24 - Time will be parsed as it would be 24 hour clock.
         
     | 
| 
       30 
     | 
    
         
            -
                #        :week_start - By default, the parser assesses weeks start on
         
     | 
| 
       31 
     | 
    
         
            -
                #                  sunday but you can change this value to :monday if
         
     | 
| 
       32 
     | 
    
         
            -
                #                  needed.
         
     | 
| 
       33 
28 
     | 
    
         
             
                #        :guess - By default the parser will guess a single point in time
         
     | 
| 
       34 
29 
     | 
    
         
             
                #                 for the given date or time. If you'd rather have the
         
     | 
| 
       35 
30 
     | 
    
         
             
                #                 entire time span returned, set this to false
         
     | 
| 
         @@ -55,9 +50,8 @@ module Chronic 
     | 
|
| 
       55 
50 
     | 
    
         
             
                #                 two digit year is `now + x years` it's assumed to be the
         
     | 
| 
       56 
51 
     | 
    
         
             
                #                 future, `now - x years` is assumed to be the past.
         
     | 
| 
       57 
52 
     | 
    
         
             
                def initialize(options = {})
         
     | 
| 
       58 
     | 
    
         
            -
                  validate_options!(options)
         
     | 
| 
       59 
53 
     | 
    
         
             
                  @options = DEFAULT_OPTIONS.merge(options)
         
     | 
| 
       60 
     | 
    
         
            -
                  @now = options 
     | 
| 
      
 54 
     | 
    
         
            +
                  @now = options.delete(:now) || Chronic.time_class.now
         
     | 
| 
       61 
55 
     | 
    
         
             
                end
         
     | 
| 
       62 
56 
     | 
    
         | 
| 
       63 
57 
     | 
    
         
             
                # Parse "text" with the given options
         
     | 
| 
         @@ -94,35 +88,22 @@ module Chronic 
     | 
|
| 
       94 
88 
     | 
    
         
             
                # Returns a new String ready for Chronic to parse.
         
     | 
| 
       95 
89 
     | 
    
         
             
                def pre_normalize(text)
         
     | 
| 
       96 
90 
     | 
    
         
             
                  text = text.to_s.downcase
         
     | 
| 
       97 
     | 
    
         
            -
                  text.gsub!(/\b(\d{ 
     | 
| 
      
 91 
     | 
    
         
            +
                  text.gsub!(/\b(\d{2})\.(\d{2})\.(\d{4})\b/, '\3 / \2 / \1')
         
     | 
| 
       98 
92 
     | 
    
         
             
                  text.gsub!(/\b([ap])\.m\.?/, '\1m')
         
     | 
| 
       99 
     | 
    
         
            -
                  text.gsub!(/(\s+|:\d{2}|:\d{2}\.\d 
     | 
| 
      
 93 
     | 
    
         
            +
                  text.gsub!(/(\s+|:\d{2}|:\d{2}\.\d{3})\-(\d{2}:?\d{2})\b/, '\1tzminus\2')
         
     | 
| 
       100 
94 
     | 
    
         
             
                  text.gsub!(/\./, ':')
         
     | 
| 
       101 
95 
     | 
    
         
             
                  text.gsub!(/([ap]):m:?/, '\1m')
         
     | 
| 
       102 
     | 
    
         
            -
                  text.gsub!(/'(\d{2})\b/) do
         
     | 
| 
       103 
     | 
    
         
            -
                    number = $1.to_i
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
                    if Chronic::Date::could_be_year?(number)
         
     | 
| 
       106 
     | 
    
         
            -
                      Chronic::Date::make_year(number, options[:ambiguous_year_future_bias])
         
     | 
| 
       107 
     | 
    
         
            -
                    else
         
     | 
| 
       108 
     | 
    
         
            -
                      number
         
     | 
| 
       109 
     | 
    
         
            -
                    end
         
     | 
| 
       110 
     | 
    
         
            -
                  end
         
     | 
| 
       111 
96 
     | 
    
         
             
                  text.gsub!(/['"]/, '')
         
     | 
| 
       112 
97 
     | 
    
         
             
                  text.gsub!(/,/, ' ')
         
     | 
| 
       113 
98 
     | 
    
         
             
                  text.gsub!(/^second /, '2nd ')
         
     | 
| 
       114 
     | 
    
         
            -
                  text.gsub!(/\bsecond (of|day|month|hour|minute|second 
     | 
| 
       115 
     | 
    
         
            -
                  text.gsub!(/\bthird quarter\b/, '3rd q')
         
     | 
| 
       116 
     | 
    
         
            -
                  text.gsub!(/\bfourth quarter\b/, '4th q')
         
     | 
| 
       117 
     | 
    
         
            -
                  text.gsub!(/quarters?(\s+|$)(?!to|till|past|after|before)/, 'q\1')
         
     | 
| 
      
 99 
     | 
    
         
            +
                  text.gsub!(/\bsecond (of|day|month|hour|minute|second)\b/, '2nd \1')
         
     | 
| 
       118 
100 
     | 
    
         
             
                  text = Numerizer.numerize(text)
         
     | 
| 
       119 
     | 
    
         
            -
                  text.gsub!(/\b(\d)(?:st|nd|rd|th)\s+q\b/, 'q\1')
         
     | 
| 
       120 
101 
     | 
    
         
             
                  text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' }
         
     | 
| 
       121 
102 
     | 
    
         
             
                  text.gsub!(/(?:^|\s)0(\d+:\d+\s*pm?\b)/, ' \1')
         
     | 
| 
       122 
103 
     | 
    
         
             
                  text.gsub!(/\btoday\b/, 'this day')
         
     | 
| 
       123 
104 
     | 
    
         
             
                  text.gsub!(/\btomm?orr?ow\b/, 'next day')
         
     | 
| 
       124 
105 
     | 
    
         
             
                  text.gsub!(/\byesterday\b/, 'last day')
         
     | 
| 
       125 
     | 
    
         
            -
                  text.gsub!(/\bnoon 
     | 
| 
      
 106 
     | 
    
         
            +
                  text.gsub!(/\bnoon\b/, '12:00pm')
         
     | 
| 
       126 
107 
     | 
    
         
             
                  text.gsub!(/\bmidnight\b/, '24:00')
         
     | 
| 
       127 
108 
     | 
    
         
             
                  text.gsub!(/\bnow\b/, 'this second')
         
     | 
| 
       128 
109 
     | 
    
         
             
                  text.gsub!('quarter', '15')
         
     | 
| 
         @@ -163,22 +144,87 @@ module Chronic 
     | 
|
| 
       163 
144 
     | 
    
         
             
                #
         
     | 
| 
       164 
145 
     | 
    
         
             
                # Returns a Hash of Handler definitions.
         
     | 
| 
       165 
146 
     | 
    
         
             
                def definitions(options = {})
         
     | 
| 
       166 
     | 
    
         
            -
                   
     | 
| 
       167 
     | 
    
         
            -
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
                  options[:endian_precedence] ||= [:middle, :little]
         
     | 
| 
       168 
148 
     | 
    
         | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
      
 149 
     | 
    
         
            +
                  @@definitions ||= {
         
     | 
| 
      
 150 
     | 
    
         
            +
                    :time => [
         
     | 
| 
      
 151 
     | 
    
         
            +
                      Handler.new([:repeater_time, :repeater_day_portion?], nil)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                    :date => [
         
     | 
| 
      
 155 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, [:separator_slash?, :separator_dash?], :time_zone, :scalar_year], :handle_generic),
         
     | 
| 
      
 156 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day], :handle_rdn_rmn_sd),
         
     | 
| 
      
 157 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :scalar_year], :handle_rdn_rmn_sd_sy),
         
     | 
| 
      
 158 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day], :handle_rdn_rmn_od),
         
     | 
| 
      
 159 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day, :scalar_year], :handle_rdn_rmn_od_sy),
         
     | 
| 
      
 160 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :separator_at?, 'time?'], :handle_rdn_rmn_sd),
         
     | 
| 
      
 161 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_rmn_od),
         
     | 
| 
      
 162 
     | 
    
         
            +
                      Handler.new([:repeater_day_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_od),
         
     | 
| 
      
 163 
     | 
    
         
            +
                      Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_day, :repeater_time, :time_zone], :handle_generic),
         
     | 
| 
      
 164 
     | 
    
         
            +
                      Handler.new([:ordinal_day], :handle_generic),
         
     | 
| 
      
 165 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy),
         
     | 
| 
      
 166 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :ordinal_day, :scalar_year], :handle_rmn_od_sy),
         
     | 
| 
      
 167 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :scalar_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_sd_sy),
         
     | 
| 
      
 168 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :ordinal_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_od_sy),
         
     | 
| 
      
 169 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, [:separator_slash?, :separator_dash?], :scalar_day, :separator_at?, 'time?'], :handle_rmn_sd),
         
     | 
| 
      
 170 
     | 
    
         
            +
                      Handler.new([:repeater_time, :repeater_day_portion?, :separator_on?, :repeater_month_name, :scalar_day], :handle_rmn_sd_on),
         
     | 
| 
      
 171 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rmn_od),
         
     | 
| 
      
 172 
     | 
    
         
            +
                      Handler.new([:ordinal_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_od_rmn_sy),
         
     | 
| 
      
 173 
     | 
    
         
            +
                      Handler.new([:ordinal_day, :repeater_month_name, :separator_at?, 'time?'], :handle_od_rmn),
         
     | 
| 
      
 174 
     | 
    
         
            +
                      Handler.new([:ordinal_day, :grabber?, :repeater_month, :separator_at?, 'time?'], :handle_od_rm),
         
     | 
| 
      
 175 
     | 
    
         
            +
                      Handler.new([:scalar_year, :repeater_month_name, :ordinal_day], :handle_sy_rmn_od),
         
     | 
| 
      
 176 
     | 
    
         
            +
                      Handler.new([:repeater_time, :repeater_day_portion?, :separator_on?, :repeater_month_name, :ordinal_day], :handle_rmn_od_on),
         
     | 
| 
      
 177 
     | 
    
         
            +
                      Handler.new([:repeater_month_name, :scalar_year], :handle_rmn_sy),
         
     | 
| 
      
 178 
     | 
    
         
            +
                      Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy),
         
     | 
| 
      
 179 
     | 
    
         
            +
                      Handler.new([:scalar_day, [:separator_slash?, :separator_dash?], :repeater_month_name, :separator_at?, 'time?'], :handle_sd_rmn),
         
     | 
| 
      
 180 
     | 
    
         
            +
                      Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd),
         
     | 
| 
      
 181 
     | 
    
         
            +
                      Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month], :handle_sy_sm),
         
     | 
| 
      
 182 
     | 
    
         
            +
                      Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_year], :handle_sm_sy),
         
     | 
| 
      
 183 
     | 
    
         
            +
                      Handler.new([:scalar_day, [:separator_slash, :separator_dash], :repeater_month_name, [:separator_slash, :separator_dash], :scalar_year, :repeater_time?], :handle_sm_rmn_sy),
         
     | 
| 
      
 184 
     | 
    
         
            +
                      Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar?, :time_zone], :handle_generic),
         
     | 
| 
      
 185 
     | 
    
         
            +
                    ],
         
     | 
| 
       170 
186 
     | 
    
         | 
| 
      
 187 
     | 
    
         
            +
                    :anchor => [
         
     | 
| 
      
 188 
     | 
    
         
            +
                      Handler.new([:separator_on?, :grabber?, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r),
         
     | 
| 
      
 189 
     | 
    
         
            +
                      Handler.new([:grabber?, :repeater, :repeater, :separator?, :repeater?, :repeater?], :handle_r),
         
     | 
| 
      
 190 
     | 
    
         
            +
                      Handler.new([:repeater, :grabber, :repeater], :handle_r_g_r)
         
     | 
| 
      
 191 
     | 
    
         
            +
                    ],
         
     | 
| 
       171 
192 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
             
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
             
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
      
 193 
     | 
    
         
            +
                    :arrow => [
         
     | 
| 
      
 194 
     | 
    
         
            +
                      Handler.new([:scalar, :repeater, :pointer], :handle_s_r_p),
         
     | 
| 
      
 195 
     | 
    
         
            +
                      Handler.new([:scalar, :repeater, :separator_and?, :scalar, :repeater, :pointer, :separator_at?, 'anchor'], :handle_s_r_a_s_r_p_a),
         
     | 
| 
      
 196 
     | 
    
         
            +
                      Handler.new([:pointer, :scalar, :repeater], :handle_p_s_r),
         
     | 
| 
      
 197 
     | 
    
         
            +
                      Handler.new([:scalar, :repeater, :pointer, :separator_at?, 'anchor'], :handle_s_r_p_a)
         
     | 
| 
      
 198 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                    :narrow => [
         
     | 
| 
      
 201 
     | 
    
         
            +
                      Handler.new([:ordinal, :repeater, :separator_in, :repeater], :handle_o_r_s_r),
         
     | 
| 
      
 202 
     | 
    
         
            +
                      Handler.new([:ordinal, :repeater, :grabber, :repeater], :handle_o_r_g_r)
         
     | 
| 
      
 203 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 204 
     | 
    
         
            +
                  }
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
                  endians = [
         
     | 
| 
      
 207 
     | 
    
         
            +
                    Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
         
     | 
| 
      
 208 
     | 
    
         
            +
                    Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sm_sd),
         
     | 
| 
      
 209 
     | 
    
         
            +
                    Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, :separator_at?, 'time?'], :handle_sd_sm),
         
     | 
| 
      
 210 
     | 
    
         
            +
                    Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
         
     | 
| 
      
 211 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  case endian = Array(options[:endian_precedence]).first
         
     | 
| 
      
 214 
     | 
    
         
            +
                  when :little
         
     | 
| 
      
 215 
     | 
    
         
            +
                    @@definitions.merge(:endian => endians.reverse)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  when :middle
         
     | 
| 
      
 217 
     | 
    
         
            +
                    @@definitions.merge(:endian => endians)
         
     | 
| 
      
 218 
     | 
    
         
            +
                  else
         
     | 
| 
      
 219 
     | 
    
         
            +
                    raise ArgumentError, "Unknown endian option '#{endian}'"
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
       177 
221 
     | 
    
         
             
                end
         
     | 
| 
       178 
222 
     | 
    
         | 
| 
      
 223 
     | 
    
         
            +
                private
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
       179 
225 
     | 
    
         
             
                def tokenize(text, options)
         
     | 
| 
       180 
226 
     | 
    
         
             
                  text = pre_normalize(text)
         
     | 
| 
       181 
     | 
    
         
            -
                  tokens =  
     | 
| 
      
 227 
     | 
    
         
            +
                  tokens = text.split(' ').map { |word| Token.new(word) }
         
     | 
| 
       182 
228 
     | 
    
         
             
                  [Repeater, Grabber, Pointer, Scalar, Ordinal, Separator, Sign, TimeZone].each do |tok|
         
     | 
| 
       183 
229 
     | 
    
         
             
                    tok.scan(tokens, options)
         
     | 
| 
       184 
230 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -215,7 +261,7 @@ module Chronic 
     | 
|
| 
       215 
261 
     | 
    
         
             
                    end
         
     | 
| 
       216 
262 
     | 
    
         
             
                  end
         
     | 
| 
       217 
263 
     | 
    
         | 
| 
       218 
     | 
    
         
            -
                  puts  
     | 
| 
      
 264 
     | 
    
         
            +
                  puts "-none" if Chronic.debug
         
     | 
| 
       219 
265 
     | 
    
         
             
                  return nil
         
     | 
| 
       220 
266 
     | 
    
         
             
                end
         
     | 
| 
       221 
267 
     | 
    
         
             
              end
         
     |