chronic-mmlac 0.6.4.2 → 0.10.2.1
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 +4 -3
- data/.travis.yml +8 -0
- data/HISTORY.md +69 -0
- data/README.md +47 -42
- data/Rakefile +28 -8
- data/chronic.gemspec +9 -3
- data/lib/chronic.rb +113 -74
- data/lib/chronic/date.rb +82 -0
- data/lib/chronic/grabber.rb +9 -7
- data/lib/chronic/handler.rb +47 -40
- data/lib/chronic/handlers.rb +210 -28
- data/lib/chronic/numerizer.rb +11 -2
- data/lib/chronic/ordinal.rb +28 -23
- data/lib/chronic/parser.rb +268 -0
- data/lib/chronic/pointer.rb +9 -7
- data/lib/chronic/repeater.rb +58 -48
- data/lib/chronic/repeaters/repeater_day.rb +4 -3
- data/lib/chronic/repeaters/repeater_day_name.rb +5 -4
- data/lib/chronic/repeaters/repeater_day_portion.rb +29 -14
- data/lib/chronic/repeaters/repeater_fortnight.rb +4 -3
- data/lib/chronic/repeaters/repeater_hour.rb +4 -3
- data/lib/chronic/repeaters/repeater_minute.rb +4 -3
- data/lib/chronic/repeaters/repeater_month.rb +5 -4
- data/lib/chronic/repeaters/repeater_month_name.rb +4 -3
- data/lib/chronic/repeaters/repeater_season.rb +5 -3
- data/lib/chronic/repeaters/repeater_second.rb +4 -3
- data/lib/chronic/repeaters/repeater_time.rb +35 -25
- data/lib/chronic/repeaters/repeater_week.rb +4 -3
- data/lib/chronic/repeaters/repeater_weekday.rb +4 -3
- data/lib/chronic/repeaters/repeater_weekend.rb +4 -3
- data/lib/chronic/repeaters/repeater_year.rb +5 -4
- data/lib/chronic/scalar.rb +40 -68
- data/lib/chronic/season.rb +1 -12
- data/lib/chronic/separator.rb +142 -23
- data/lib/chronic/sign.rb +49 -0
- data/lib/chronic/span.rb +2 -2
- data/lib/chronic/tag.rb +10 -15
- data/lib/chronic/time.rb +40 -0
- data/lib/chronic/time_zone.rb +9 -7
- data/lib/chronic/token.rb +16 -10
- data/test/helper.rb +7 -1
- data/test/{test_Chronic.rb → test_chronic.rb} +69 -34
- data/test/{test_DaylightSavings.rb → test_daylight_savings.rb} +1 -1
- data/test/{test_Handler.rb → test_handler.rb} +38 -14
- data/test/{test_MiniDate.rb → test_mini_date.rb} +9 -9
- data/test/{test_Numerizer.rb → test_numerizer.rb} +16 -2
- data/test/test_parsing.rb +367 -18
- data/test/{test_RepeaterDayName.rb → test_repeater_day_name.rb} +1 -1
- data/test/test_repeater_day_portion.rb +254 -0
- data/test/{test_RepeaterFortnight.rb → test_repeater_fortnight.rb} +1 -1
- data/test/{test_RepeaterHour.rb → test_repeater_hour.rb} +1 -1
- data/test/{test_RepeaterMinute.rb → test_repeater_minute.rb} +1 -1
- data/test/{test_RepeaterMonth.rb → test_repeater_month.rb} +1 -1
- data/test/{test_RepeaterMonthName.rb → test_repeater_month_name.rb} +1 -1
- data/test/{test_RepeaterSeason.rb → test_repeater_season.rb} +1 -1
- data/test/{test_RepeaterTime.rb → test_repeater_time.rb} +19 -1
- data/test/{test_RepeaterWeek.rb → test_repeater_week.rb} +1 -1
- data/test/{test_RepeaterWeekday.rb → test_repeater_weekday.rb} +1 -1
- data/test/{test_RepeaterWeekend.rb → test_repeater_weekend.rb} +1 -1
- data/test/{test_RepeaterYear.rb → test_repeater_year.rb} +1 -1
- data/test/{test_Span.rb → test_span.rb} +2 -2
- data/test/{test_Token.rb → test_token.rb} +1 -1
- metadata +107 -46
- data/.gemtest +0 -0
- data/.yardopts +0 -3
- data/lib/chronic/chronic.rb +0 -325
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64794a6186c6495e6c7e10a36f6a144314e989c4
|
|
4
|
+
data.tar.gz: dea5dd4fa693f047fe6be705ec6d42371d4231e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3134feb1bee6ff0a14244742e39a30c309755e54b871c5ec11c8405fbded5f3c086f005f2f16707e82050ecfa6090fd3300a6565e2e0d5fb198a47cbd48d8c7c
|
|
7
|
+
data.tar.gz: b4c753fe1c44c66dd7d56f4f943cdb71e7ba19f410db75f1bd035f5e383a4499d633fc6fc562f22921b8e297dbc2234509a6122db0388adeef077b1ce1d05178
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/HISTORY.md
CHANGED
|
@@ -1,3 +1,72 @@
|
|
|
1
|
+
# 0.10.2 / 2013-09-09
|
|
2
|
+
|
|
3
|
+
* Fix 1.8.7 support (due to be dropped in 0.11.0)
|
|
4
|
+
* Bugfix for times with negative zones
|
|
5
|
+
|
|
6
|
+
# 0.10.1 / 2013-08-27
|
|
7
|
+
|
|
8
|
+
* Support `ActiveSupport::TimeZone` (#209, #208)
|
|
9
|
+
|
|
10
|
+
# 0.10.0 / 2013-08-25
|
|
11
|
+
|
|
12
|
+
* Chronic will parse subseconds correctly
|
|
13
|
+
for all supported date/time formats (#195, #198 and #200)
|
|
14
|
+
* Support for date format: dd.mm.yyyy (#197)
|
|
15
|
+
* Option `:hours24` to parse as 24 hour clock (#201 and #202)
|
|
16
|
+
* `:guess` option allows to specify which part of Span to return.
|
|
17
|
+
(accepted values `false`,`true`,`:begin`, `:middle`, `:end`)
|
|
18
|
+
* Replace `rcov` with `SimpleCov` for coverage generation
|
|
19
|
+
* Add more tests
|
|
20
|
+
* Various changes in codebase (#202 and #206)
|
|
21
|
+
|
|
22
|
+
# 0.9.1 / 2013-02-25
|
|
23
|
+
|
|
24
|
+
* Ensure Chronic strips periods from day portions (#173)
|
|
25
|
+
* Properly numerize "twelfth", "twentieth" etc. (#172, James McKinney)
|
|
26
|
+
* Ensure Chronic is compatible with Ruby 2.0.0 (#165, Ravil Bayramgalin)
|
|
27
|
+
|
|
28
|
+
# 0.9.0 / 2012-12-21
|
|
29
|
+
|
|
30
|
+
* Implement Chronic::Parser class and create an instance of this class
|
|
31
|
+
instead of leaving all data in the class level of Chronic
|
|
32
|
+
* Various bug fixes
|
|
33
|
+
* Add support for excel date formats (#149, @jmondo)
|
|
34
|
+
* Added support for time expressions such as '10 till' or 'half
|
|
35
|
+
past two' (#146, @chicagogrooves)
|
|
36
|
+
* Add support for RepeaterDayName, RepeaterMonthName,
|
|
37
|
+
Ordinal/ScalarDay and Time (#153, @kareemk)
|
|
38
|
+
|
|
39
|
+
# 0.8.0 / 2012-09-16
|
|
40
|
+
|
|
41
|
+
* Support parsing "<ordinal> of this month" (#109)
|
|
42
|
+
* Support parsing ISO 8601 format (#115)
|
|
43
|
+
* Support parsing "on <day>" without a timestamp (#117)
|
|
44
|
+
* Fix time parsing regexp (#125)
|
|
45
|
+
* Support time when parsing dd-mm-yyy <time> (#126)
|
|
46
|
+
* Allow anchor handler to accept any separators (at, on) (#128)
|
|
47
|
+
* Support parsing EXIF date format (#112)
|
|
48
|
+
* Start using minitest for testing
|
|
49
|
+
* Ensure periods are interpreted as colons (#81).
|
|
50
|
+
* Support month/day and day/month parsing (#59).
|
|
51
|
+
* Support day(scalar)-month(name)-year(scalar) (#99).
|
|
52
|
+
* Handle text starting with 'a' or 'an' (#101, @steveburkett).
|
|
53
|
+
* Ensure post medium timestamps are correctly formatted (#89)
|
|
54
|
+
|
|
55
|
+
# 0.6.7 / 2012-01-31
|
|
56
|
+
|
|
57
|
+
* Handle day, month names with scalar day and year (Joe Fiorini)
|
|
58
|
+
* Ensure 31st parses correctly with day names (Joe Fiorini)
|
|
59
|
+
|
|
60
|
+
# 0.6.6 / 2011-11-23
|
|
61
|
+
|
|
62
|
+
* `Chronic.parse('thur')` no longer returns `nil` (@harold)
|
|
63
|
+
|
|
64
|
+
# 0.6.5 / 2011-11-04
|
|
65
|
+
|
|
66
|
+
* Fix bug when parsing ordinal repeaters (#73)
|
|
67
|
+
* Added handler support for day_name month_name (@imme5150)
|
|
68
|
+
* Fix bug when parsing strings prefixed with PM
|
|
69
|
+
|
|
1
70
|
# 0.6.4 / 2011-08-08
|
|
2
71
|
|
|
3
72
|
* Fixed bug where 'noon' was parsed as 00:00 rather than 12:00
|
data/README.md
CHANGED
|
@@ -1,56 +1,54 @@
|
|
|
1
1
|
Chronic
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
-
## DESCRIPTION
|
|
5
|
-
|
|
6
4
|
Chronic is a natural language date/time parser written in pure Ruby. See below
|
|
7
5
|
for the wide variety of formats Chronic will parse.
|
|
8
6
|
|
|
7
|
+
## Installation
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
$ [sudo] gem install chronic
|
|
9
|
+
```
|
|
10
|
+
$ gem install chronic
|
|
11
|
+
```
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
## Usage
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
$ gem install chronic-<version>.gem
|
|
15
|
+
```ruby
|
|
16
|
+
require 'chronic'
|
|
21
17
|
|
|
18
|
+
Time.now #=> Sun Aug 27 23:18:25 PDT 2006
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
Chronic.parse('tomorrow')
|
|
21
|
+
#=> Mon Aug 28 12:00:00 PDT 2006
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
Chronic.parse('monday', :context => :past)
|
|
24
|
+
#=> Mon Aug 21 12:00:00 PDT 2006
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
Chronic.parse('this tuesday 5:00')
|
|
27
|
+
#=> Tue Aug 29 17:00:00 PDT 2006
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
Chronic.parse('this tuesday 5:00', :ambiguous_time_range => :none)
|
|
30
|
+
#=> Tue Aug 29 05:00:00 PDT 2006
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
Chronic.parse('may 27th', :now => Time.local(2000, 1, 1))
|
|
33
|
+
#=> Sat May 27 12:00:00 PDT 2000
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
Chronic.parse('may 27th', :guess => false)
|
|
36
|
+
#=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
Chronic.parse('6/4/2012', :endian_precedence => :little)
|
|
39
|
+
#=> Fri Apr 06 00:00:00 PDT 2012
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
Chronic.parse('INVALID DATE')
|
|
42
|
+
#=> nil
|
|
43
|
+
```
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Chronic.parse('may 27th', :guess => false)
|
|
48
|
-
#=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007
|
|
45
|
+
If the parser can find a date or time, either a Time or Chronic::Span
|
|
46
|
+
will be returned (depending on the value of `:guess`). If no
|
|
47
|
+
date or time can be found, `nil` will be returned.
|
|
49
48
|
|
|
50
49
|
See `Chronic.parse` for detailed usage instructions.
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
## EXAMPLES
|
|
51
|
+
## Examples
|
|
54
52
|
|
|
55
53
|
Chronic can parse a huge variety of date and time formats. Following is a
|
|
56
54
|
small sample of strings that will be properly parsed. Parsing is case
|
|
@@ -64,12 +62,17 @@ Simple
|
|
|
64
62
|
* friday 13:00
|
|
65
63
|
* mon 2:35
|
|
66
64
|
* 4pm
|
|
65
|
+
* 10 to 8
|
|
66
|
+
* 10 past 2
|
|
67
|
+
* half past 2
|
|
67
68
|
* 6 in the morning
|
|
68
69
|
* friday 1pm
|
|
69
70
|
* sat 7 in the evening
|
|
70
71
|
* yesterday
|
|
71
72
|
* today
|
|
72
73
|
* tomorrow
|
|
74
|
+
* last week
|
|
75
|
+
* next week
|
|
73
76
|
* this tuesday
|
|
74
77
|
* next month
|
|
75
78
|
* last winter
|
|
@@ -86,6 +89,7 @@ Simple
|
|
|
86
89
|
Complex
|
|
87
90
|
|
|
88
91
|
* 3 years ago
|
|
92
|
+
* a year ago
|
|
89
93
|
* 5 months before now
|
|
90
94
|
* 7 hours ago
|
|
91
95
|
* 7 days from now
|
|
@@ -131,10 +135,11 @@ Specific Times (many of the above with an added time)
|
|
|
131
135
|
* January 5 at 7pm
|
|
132
136
|
* 22nd of june at 8am
|
|
133
137
|
* 1979-05-27 05:00:00
|
|
138
|
+
* 03/01/2012 07:25:09.234567
|
|
134
139
|
* etc
|
|
135
140
|
|
|
136
141
|
|
|
137
|
-
##
|
|
142
|
+
## Time Zones
|
|
138
143
|
|
|
139
144
|
Chronic allows you to set which Time class to use when constructing times. By
|
|
140
145
|
default, the built in Ruby time class creates times in your system's local
|
|
@@ -142,13 +147,14 @@ time zone. You can set this to something like ActiveSupport's
|
|
|
142
147
|
[TimeZone](http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html)
|
|
143
148
|
class to get full time zone support.
|
|
144
149
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
```
|
|
151
|
+
>> Time.zone = "UTC"
|
|
152
|
+
>> Chronic.time_class = Time.zone
|
|
153
|
+
>> Chronic.parse("June 15 2006 at 5:45 AM")
|
|
154
|
+
=> Thu, 15 Jun 2006 05:45:00 UTC +00:00
|
|
155
|
+
```
|
|
150
156
|
|
|
151
|
-
##
|
|
157
|
+
## Limitations
|
|
152
158
|
|
|
153
159
|
Chronic uses Ruby's built in Time class for all time storage and computation.
|
|
154
160
|
Because of this, only times that the Time class can handle will be properly
|
|
@@ -156,20 +162,19 @@ parsed. Parsing for times outside of this range will simply return nil.
|
|
|
156
162
|
Support for a wider range of times is planned for a future release.
|
|
157
163
|
|
|
158
164
|
|
|
159
|
-
##
|
|
165
|
+
## Contribute
|
|
160
166
|
|
|
161
167
|
If you'd like to hack on Chronic, start by forking the repo on GitHub:
|
|
162
168
|
|
|
163
169
|
https://github.com/mojombo/chronic
|
|
164
170
|
|
|
165
|
-
|
|
166
|
-
your changes merged back into core is as follows:
|
|
171
|
+
The best way to get your changes merged back into core is as follows:
|
|
167
172
|
|
|
168
173
|
1. Clone down your fork
|
|
169
174
|
1. Create a thoughtfully named topic branch to contain your change
|
|
170
175
|
1. Hack away
|
|
171
176
|
1. Add tests and make sure everything still passes by running `rake`
|
|
172
|
-
1. Ensure your tests pass in multiple timezones
|
|
177
|
+
1. Ensure your tests pass in multiple timezones. ie `TZ=utc rake` `TZ=BST rake`
|
|
173
178
|
1. If you are adding new functionality, document it in the README
|
|
174
179
|
1. Do not change the version number, we will do that on our end
|
|
175
180
|
1. If necessary, rebase your commits into logical chunks, without errors
|
data/Rakefile
CHANGED
|
@@ -5,17 +5,37 @@ def version
|
|
|
5
5
|
contents[/VERSION = "([^"]+)"/, 1]
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
def do_test
|
|
9
9
|
$:.unshift './test'
|
|
10
10
|
Dir.glob('test/test_*.rb').each { |t| require File.basename(t) }
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
def open_command
|
|
14
|
+
case RUBY_PLATFORM
|
|
15
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
16
|
+
'start'
|
|
17
|
+
when /darwin|mac os/
|
|
18
|
+
'open'
|
|
19
|
+
else
|
|
20
|
+
'xdg-open'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
task :test do
|
|
25
|
+
do_test
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "Generate SimpleCov test coverage and open in your browser"
|
|
14
29
|
task :coverage do
|
|
15
|
-
require '
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
require 'simplecov'
|
|
31
|
+
FileUtils.rm_rf("./coverage")
|
|
32
|
+
SimpleCov.command_name 'Unit Tests'
|
|
33
|
+
SimpleCov.at_exit do
|
|
34
|
+
SimpleCov.result.format!
|
|
35
|
+
sh "#{open_command} #{SimpleCov.coverage_path}/index.html"
|
|
36
|
+
end
|
|
37
|
+
SimpleCov.start
|
|
38
|
+
do_test
|
|
19
39
|
end
|
|
20
40
|
|
|
21
41
|
desc "Open an irb session preloaded with this library"
|
|
@@ -38,9 +58,9 @@ end
|
|
|
38
58
|
|
|
39
59
|
desc "Build a gem from the gemspec"
|
|
40
60
|
task :build do
|
|
41
|
-
|
|
61
|
+
FileUtils.mkdir_p "pkg"
|
|
42
62
|
sh "gem build chronic.gemspec"
|
|
43
|
-
|
|
63
|
+
FileUtils.mv("./chronic-#{version}.gem", "pkg")
|
|
44
64
|
end
|
|
45
65
|
|
|
46
66
|
task :default => :test
|
data/chronic.gemspec
CHANGED
|
@@ -8,10 +8,16 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.summary = 'Natural language date/time parsing.'
|
|
9
9
|
s.description = 'Chronic is a natural language date/time parser written in pure Ruby.'
|
|
10
10
|
s.authors = ['Tom Preston-Werner', 'Lee Jarvis']
|
|
11
|
-
s.email = ['tom@mojombo.com', '
|
|
11
|
+
s.email = ['tom@mojombo.com', 'ljjarvis@gmail.com']
|
|
12
12
|
s.homepage = 'http://github.com/mojombo/chronic'
|
|
13
|
+
s.license = 'MIT'
|
|
13
14
|
s.rdoc_options = ['--charset=UTF-8']
|
|
14
15
|
s.extra_rdoc_files = %w[README.md HISTORY.md LICENSE]
|
|
15
|
-
s.files = `git ls-files`.split(
|
|
16
|
-
s.test_files = `git ls-files -- test`.split(
|
|
16
|
+
s.files = `git ls-files`.split($/)
|
|
17
|
+
s.test_files = `git ls-files -- test`.split($/)
|
|
18
|
+
|
|
19
|
+
s.add_development_dependency 'rake'
|
|
20
|
+
s.add_development_dependency 'simplecov'
|
|
21
|
+
s.add_development_dependency 'minitest', '~> 5.0'
|
|
22
|
+
s.add_development_dependency 'activesupport'
|
|
17
23
|
end
|
data/lib/chronic.rb
CHANGED
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
require 'time'
|
|
2
2
|
require 'date'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
require 'chronic/parser'
|
|
5
|
+
require 'chronic/date'
|
|
6
|
+
require 'chronic/time'
|
|
7
|
+
|
|
8
|
+
require 'chronic/handler'
|
|
9
|
+
require 'chronic/handlers'
|
|
10
|
+
require 'chronic/mini_date'
|
|
11
|
+
require 'chronic/tag'
|
|
12
|
+
require 'chronic/span'
|
|
13
|
+
require 'chronic/token'
|
|
14
|
+
require 'chronic/grabber'
|
|
15
|
+
require 'chronic/pointer'
|
|
16
|
+
require 'chronic/scalar'
|
|
17
|
+
require 'chronic/ordinal'
|
|
18
|
+
require 'chronic/separator'
|
|
19
|
+
require 'chronic/sign'
|
|
20
|
+
require 'chronic/time_zone'
|
|
21
|
+
require 'chronic/numerizer'
|
|
22
|
+
require 'chronic/season'
|
|
23
|
+
|
|
24
|
+
require 'chronic/repeater'
|
|
25
|
+
require 'chronic/repeaters/repeater_year'
|
|
26
|
+
require 'chronic/repeaters/repeater_season'
|
|
27
|
+
require 'chronic/repeaters/repeater_season_name'
|
|
28
|
+
require 'chronic/repeaters/repeater_month'
|
|
29
|
+
require 'chronic/repeaters/repeater_month_name'
|
|
30
|
+
require 'chronic/repeaters/repeater_fortnight'
|
|
31
|
+
require 'chronic/repeaters/repeater_week'
|
|
32
|
+
require 'chronic/repeaters/repeater_weekend'
|
|
33
|
+
require 'chronic/repeaters/repeater_weekday'
|
|
34
|
+
require 'chronic/repeaters/repeater_day'
|
|
35
|
+
require 'chronic/repeaters/repeater_day_name'
|
|
36
|
+
require 'chronic/repeaters/repeater_day_portion'
|
|
37
|
+
require 'chronic/repeaters/repeater_hour'
|
|
38
|
+
require 'chronic/repeaters/repeater_minute'
|
|
39
|
+
require 'chronic/repeaters/repeater_second'
|
|
40
|
+
require 'chronic/repeaters/repeater_time'
|
|
41
|
+
|
|
42
|
+
# Parse natural language dates and times into Time or Chronic::Span objects.
|
|
43
|
+
#
|
|
44
|
+
# Examples:
|
|
5
45
|
#
|
|
6
|
-
# @example
|
|
7
46
|
# require 'chronic'
|
|
8
47
|
#
|
|
9
48
|
# Time.now #=> Sun Aug 27 23:18:25 PDT 2006
|
|
@@ -13,29 +52,16 @@ require 'date'
|
|
|
13
52
|
#
|
|
14
53
|
# Chronic.parse('monday', :context => :past)
|
|
15
54
|
# #=> Mon Aug 21 12:00:00 PDT 2006
|
|
16
|
-
#
|
|
17
|
-
# Chronic.parse('this tuesday 5:00')
|
|
18
|
-
# #=> Tue Aug 29 17:00:00 PDT 2006
|
|
19
|
-
#
|
|
20
|
-
# Chronic.parse('this tuesday 5:00', :ambiguous_time_range => :none)
|
|
21
|
-
# #=> Tue Aug 29 05:00:00 PDT 2006
|
|
22
|
-
#
|
|
23
|
-
# Chronic.parse('may 27th', :now => Time.local(2000, 1, 1))
|
|
24
|
-
# #=> Sat May 27 12:00:00 PDT 2000
|
|
25
|
-
#
|
|
26
|
-
# Chronic.parse('may 27th', :guess => false)
|
|
27
|
-
# #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007
|
|
28
|
-
#
|
|
29
|
-
# @author Tom Preston-Werner, Lee Jarvis
|
|
30
55
|
module Chronic
|
|
31
|
-
VERSION = "0.
|
|
56
|
+
VERSION = "0.10.2.1"
|
|
32
57
|
|
|
33
58
|
class << self
|
|
34
59
|
|
|
35
|
-
#
|
|
60
|
+
# Returns true when debug mode is enabled.
|
|
36
61
|
attr_accessor :debug
|
|
37
62
|
|
|
38
|
-
#
|
|
63
|
+
# Examples:
|
|
64
|
+
#
|
|
39
65
|
# require 'chronic'
|
|
40
66
|
# require 'active_support/time'
|
|
41
67
|
#
|
|
@@ -44,20 +70,7 @@ module Chronic
|
|
|
44
70
|
# Chronic.parse('June 15 2006 at 5:54 AM')
|
|
45
71
|
# # => Thu, 15 Jun 2006 05:45:00 UTC +00:00
|
|
46
72
|
#
|
|
47
|
-
#
|
|
48
|
-
attr_accessor :time_class
|
|
49
|
-
|
|
50
|
-
# The current Time Chronic is using to base from
|
|
51
|
-
#
|
|
52
|
-
# @example
|
|
53
|
-
# Time.now #=> 2011-06-06 14:13:43 +0100
|
|
54
|
-
# Chronic.parse('yesterday') #=> 2011-06-05 12:00:00 +0100
|
|
55
|
-
#
|
|
56
|
-
# now = Time.local(2025, 12, 24)
|
|
57
|
-
# Chronic.parse('tomorrow', :now => now) #=> 2025-12-25 12:00:00 +0000
|
|
58
|
-
#
|
|
59
|
-
# @return [Time, nil]
|
|
60
|
-
attr_accessor :now
|
|
73
|
+
# Returns The Time class Chronic uses internally.
|
|
61
74
|
|
|
62
75
|
# To ensure thread safety, this value is thread-local.
|
|
63
76
|
def time_class
|
|
@@ -69,50 +82,76 @@ module Chronic
|
|
|
69
82
|
end
|
|
70
83
|
|
|
71
84
|
self.debug = false
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
require 'chronic/chronic'
|
|
75
|
-
require 'chronic/handler'
|
|
76
|
-
require 'chronic/handlers'
|
|
77
|
-
require 'chronic/mini_date'
|
|
78
|
-
require 'chronic/tag'
|
|
79
|
-
require 'chronic/span'
|
|
80
|
-
require 'chronic/token'
|
|
81
|
-
require 'chronic/grabber'
|
|
82
|
-
require 'chronic/pointer'
|
|
83
|
-
require 'chronic/scalar'
|
|
84
|
-
require 'chronic/ordinal'
|
|
85
|
-
require 'chronic/separator'
|
|
86
|
-
require 'chronic/time_zone'
|
|
87
|
-
require 'chronic/numerizer'
|
|
88
|
-
require 'chronic/season'
|
|
85
|
+
self.time_class = ::Time
|
|
89
86
|
|
|
90
|
-
require 'chronic/repeater'
|
|
91
|
-
require 'chronic/repeaters/repeater_year'
|
|
92
|
-
require 'chronic/repeaters/repeater_season'
|
|
93
|
-
require 'chronic/repeaters/repeater_season_name'
|
|
94
|
-
require 'chronic/repeaters/repeater_month'
|
|
95
|
-
require 'chronic/repeaters/repeater_month_name'
|
|
96
|
-
require 'chronic/repeaters/repeater_fortnight'
|
|
97
|
-
require 'chronic/repeaters/repeater_week'
|
|
98
|
-
require 'chronic/repeaters/repeater_weekend'
|
|
99
|
-
require 'chronic/repeaters/repeater_weekday'
|
|
100
|
-
require 'chronic/repeaters/repeater_day'
|
|
101
|
-
require 'chronic/repeaters/repeater_day_name'
|
|
102
|
-
require 'chronic/repeaters/repeater_day_portion'
|
|
103
|
-
require 'chronic/repeaters/repeater_hour'
|
|
104
|
-
require 'chronic/repeaters/repeater_minute'
|
|
105
|
-
require 'chronic/repeaters/repeater_second'
|
|
106
|
-
require 'chronic/repeaters/repeater_time'
|
|
107
87
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
88
|
+
# Parses a string containing a natural language date or time.
|
|
89
|
+
#
|
|
90
|
+
# If the parser can find a date or time, either a Time or Chronic::Span
|
|
91
|
+
# will be returned (depending on the value of `:guess`). If no
|
|
92
|
+
# date or time can be found, `nil` will be returned.
|
|
93
|
+
#
|
|
94
|
+
# text - The String text to parse.
|
|
95
|
+
# opts - An optional Hash of configuration options passed to Parser::new.
|
|
96
|
+
def self.parse(text, options = {})
|
|
97
|
+
Parser.new(options).parse(text)
|
|
112
98
|
end
|
|
113
99
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
100
|
+
# Construct a new time object determining possible month overflows
|
|
101
|
+
# and leap years.
|
|
102
|
+
#
|
|
103
|
+
# year - Integer year.
|
|
104
|
+
# month - Integer month.
|
|
105
|
+
# day - Integer day.
|
|
106
|
+
# hour - Integer hour.
|
|
107
|
+
# minute - Integer minute.
|
|
108
|
+
# second - Integer second.
|
|
109
|
+
#
|
|
110
|
+
# Returns a new Time object constructed from these params.
|
|
111
|
+
def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, offset = nil)
|
|
112
|
+
if second >= 60
|
|
113
|
+
minute += second / 60
|
|
114
|
+
second = second % 60
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if minute >= 60
|
|
118
|
+
hour += minute / 60
|
|
119
|
+
minute = minute % 60
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
if hour >= 24
|
|
123
|
+
day += hour / 24
|
|
124
|
+
hour = hour % 24
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# determine if there is a day overflow. this is complicated by our crappy calendar
|
|
128
|
+
# system (non-constant number of days per month)
|
|
129
|
+
day <= 56 || raise("day must be no more than 56 (makes month resolution easier)")
|
|
130
|
+
if day > 28 # no month ever has fewer than 28 days, so only do this if necessary
|
|
131
|
+
days_this_month = ::Date.leap?(year) ? Date::MONTH_DAYS_LEAP[month] : Date::MONTH_DAYS[month]
|
|
132
|
+
if day > days_this_month
|
|
133
|
+
month += day / days_this_month
|
|
134
|
+
day = day % days_this_month
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if month > 12
|
|
139
|
+
if month % 12 == 0
|
|
140
|
+
year += (month - 12) / 12
|
|
141
|
+
month = 12
|
|
142
|
+
else
|
|
143
|
+
year += month / 12
|
|
144
|
+
month = month % 12
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
if Chronic.time_class.name == "Date"
|
|
148
|
+
Chronic.time_class.new(year, month, day)
|
|
149
|
+
elsif not Chronic.time_class.respond_to?(:new) or (RUBY_VERSION.to_f < 1.9 and Chronic.time_class.name == "Time")
|
|
150
|
+
Chronic.time_class.local(year, month, day, hour, minute, second)
|
|
151
|
+
else
|
|
152
|
+
offset = Time::normalize_offset(offset) if Chronic.time_class.name == "DateTime"
|
|
153
|
+
Chronic.time_class.new(year, month, day, hour, minute, second, offset)
|
|
154
|
+
end
|
|
117
155
|
end
|
|
156
|
+
|
|
118
157
|
end
|