chronic 0.4.1 → 0.4.3
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.
- data/.gitignore +4 -0
- data/.yardopts +3 -0
- data/HISTORY.md +9 -2
- data/Rakefile +9 -101
- data/chronic.gemspec +12 -78
- data/lib/chronic/chronic.rb +222 -91
- data/lib/chronic/grabber.rb +12 -3
- data/lib/chronic/handlers.rb +44 -186
- data/lib/chronic/mini_date.rb +6 -2
- data/lib/chronic/ordinal.rb +15 -4
- data/lib/chronic/pointer.rb +12 -3
- data/lib/chronic/repeater.rb +27 -8
- data/lib/chronic/repeaters/repeater_month.rb +13 -1
- data/lib/chronic/repeaters/repeater_time.rb +1 -1
- data/lib/chronic/scalar.rb +29 -1
- data/lib/chronic/separator.rb +24 -7
- data/lib/chronic/tag.rb +10 -1
- data/lib/chronic/time_zone.rb +12 -3
- data/lib/chronic/token.rb +14 -4
- data/lib/chronic.rb +60 -47
- data/test/test_Chronic.rb +52 -2
- data/test/test_RepeaterMonth.rb +4 -0
- data/test/test_parsing.rb +6 -0
- metadata +20 -4
data/lib/chronic/separator.rb
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class Separator < Tag
|
|
2
|
+
class Separator < Tag
|
|
3
|
+
|
|
4
|
+
# Scan an Array of {Token}s and apply any necessary Separator tags to
|
|
5
|
+
# each token
|
|
6
|
+
#
|
|
7
|
+
# @param [Array<Token>] tokens Array of tokens to scan
|
|
8
|
+
# @param [Hash] options Options specified in {Chronic.parse}
|
|
9
|
+
# @return [Array] list of tokens
|
|
3
10
|
def self.scan(tokens, options)
|
|
4
|
-
tokens.
|
|
5
|
-
if t = scan_for_commas(
|
|
6
|
-
if t = scan_for_slash_or_dash(
|
|
7
|
-
if t = scan_for_at(
|
|
8
|
-
if t = scan_for_in(
|
|
9
|
-
if t = scan_for_on(
|
|
11
|
+
tokens.each do |token|
|
|
12
|
+
if t = scan_for_commas(token) then token.tag(t); next end
|
|
13
|
+
if t = scan_for_slash_or_dash(token) then token.tag(t); next end
|
|
14
|
+
if t = scan_for_at(token) then token.tag(t); next end
|
|
15
|
+
if t = scan_for_in(token) then token.tag(t); next end
|
|
16
|
+
if t = scan_for_on(token) then token.tag(t); next end
|
|
10
17
|
end
|
|
11
18
|
end
|
|
12
19
|
|
|
20
|
+
# @param [Token] token
|
|
21
|
+
# @return [SeparatorComma, nil]
|
|
13
22
|
def self.scan_for_commas(token)
|
|
14
23
|
scan_for token, SeparatorComma, { /^,$/ => :comma }
|
|
15
24
|
end
|
|
16
25
|
|
|
26
|
+
# @param [Token] token
|
|
27
|
+
# @return [SeparatorSlashOrDash, nil]
|
|
17
28
|
def self.scan_for_slash_or_dash(token)
|
|
18
29
|
scan_for token, SeparatorSlashOrDash,
|
|
19
30
|
{
|
|
@@ -22,14 +33,20 @@ module Chronic
|
|
|
22
33
|
}
|
|
23
34
|
end
|
|
24
35
|
|
|
36
|
+
# @param [Token] token
|
|
37
|
+
# @return [SeparatorAt, nil]
|
|
25
38
|
def self.scan_for_at(token)
|
|
26
39
|
scan_for token, SeparatorAt, { /^(at|@)$/ => :at }
|
|
27
40
|
end
|
|
28
41
|
|
|
42
|
+
# @param [Token] token
|
|
43
|
+
# @return [SeparatorIn, nil]
|
|
29
44
|
def self.scan_for_in(token)
|
|
30
45
|
scan_for token, SeparatorIn, { /^in$/ => :in }
|
|
31
46
|
end
|
|
32
47
|
|
|
48
|
+
# @param [Token] token
|
|
49
|
+
# @return [SeparatorOn, nil]
|
|
33
50
|
def self.scan_for_on(token)
|
|
34
51
|
scan_for token, SeparatorOn, { /^on$/ => :on }
|
|
35
52
|
end
|
data/lib/chronic/tag.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
module Chronic
|
|
2
2
|
# Tokens are tagged with subclassed instances of this class when
|
|
3
3
|
# they match specific criteria
|
|
4
|
-
class Tag
|
|
4
|
+
class Tag
|
|
5
|
+
|
|
6
|
+
# @return [Symbol]
|
|
5
7
|
attr_accessor :type
|
|
6
8
|
|
|
9
|
+
# @param [Symbol] type
|
|
7
10
|
def initialize(type)
|
|
8
11
|
@type = type
|
|
9
12
|
end
|
|
10
13
|
|
|
14
|
+
# @param [Time] s Set the start timestamp for this Tag
|
|
11
15
|
def start=(s)
|
|
12
16
|
@now = s
|
|
13
17
|
end
|
|
@@ -15,6 +19,11 @@ module Chronic
|
|
|
15
19
|
class << self
|
|
16
20
|
private
|
|
17
21
|
|
|
22
|
+
# @param [Token] token
|
|
23
|
+
# @param [Class] klass The class instance to create
|
|
24
|
+
# @param [Regexp, Hash] items
|
|
25
|
+
# @return [Object, nil] either a new instance of `klass` or `nil` if
|
|
26
|
+
# no match is found
|
|
18
27
|
def scan_for(token, klass, items={})
|
|
19
28
|
case items
|
|
20
29
|
when Regexp
|
data/lib/chronic/time_zone.rb
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class TimeZone < Tag
|
|
2
|
+
class TimeZone < Tag
|
|
3
|
+
|
|
4
|
+
# Scan an Array of {Token}s and apply any necessary TimeZone tags to
|
|
5
|
+
# each token
|
|
6
|
+
#
|
|
7
|
+
# @param [Array<Token>] tokens Array of tokens to scan
|
|
8
|
+
# @param [Hash] options Options specified in {Chronic.parse}
|
|
9
|
+
# @return [Array] list of tokens
|
|
3
10
|
def self.scan(tokens, options)
|
|
4
|
-
tokens.
|
|
5
|
-
if t = scan_for_all(
|
|
11
|
+
tokens.each do |token|
|
|
12
|
+
if t = scan_for_all(token) then token.tag(t); next end
|
|
6
13
|
end
|
|
7
14
|
end
|
|
8
15
|
|
|
16
|
+
# @param [Token] token
|
|
17
|
+
# @return [TimeZone, nil]
|
|
9
18
|
def self.scan_for_all(token)
|
|
10
19
|
scan_for token, self,
|
|
11
20
|
{
|
data/lib/chronic/token.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class Token
|
|
3
|
-
|
|
2
|
+
class Token
|
|
3
|
+
|
|
4
|
+
# @return [String] The word this Token represents
|
|
5
|
+
attr_accessor :word
|
|
6
|
+
|
|
7
|
+
# @return [Array] A list of tag associated with this Token
|
|
8
|
+
attr_accessor :tags
|
|
4
9
|
|
|
5
10
|
def initialize(word)
|
|
6
11
|
@word = word
|
|
@@ -8,21 +13,26 @@ module Chronic
|
|
|
8
13
|
end
|
|
9
14
|
|
|
10
15
|
# Tag this token with the specified tag
|
|
16
|
+
#
|
|
17
|
+
# @param [Tag] new_tag A instance of {Tag} or one of its subclasses
|
|
11
18
|
def tag(new_tag)
|
|
12
19
|
@tags << new_tag
|
|
13
20
|
end
|
|
14
21
|
|
|
15
22
|
# Remove all tags of the given class
|
|
23
|
+
#
|
|
24
|
+
# @param [Class] The tag class to remove
|
|
16
25
|
def untag(tag_class)
|
|
17
26
|
@tags.delete_if { |m| m.kind_of? tag_class }
|
|
18
27
|
end
|
|
19
28
|
|
|
20
|
-
#
|
|
29
|
+
# @return [Boolean] true if this token has any tags
|
|
21
30
|
def tagged?
|
|
22
31
|
@tags.size > 0
|
|
23
32
|
end
|
|
24
33
|
|
|
25
|
-
#
|
|
34
|
+
# @param [Class] tag_class The tag class to search for
|
|
35
|
+
# @return [Tag] The first Tag that matches the given class
|
|
26
36
|
def get_tag(tag_class)
|
|
27
37
|
@tags.find { |m| m.kind_of? tag_class }
|
|
28
38
|
end
|
data/lib/chronic.rb
CHANGED
|
@@ -1,33 +1,82 @@
|
|
|
1
|
-
|
|
1
|
+
require 'time'
|
|
2
|
+
require 'date'
|
|
3
|
+
|
|
4
|
+
# Parse natural language dates and times into Time or {Chronic::Span} objects
|
|
2
5
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Purpose: Parse natural language dates and times into Time or
|
|
6
|
-
# Chronic::Span objects
|
|
6
|
+
# @example
|
|
7
|
+
# require 'chronic'
|
|
7
8
|
#
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
# Time.now #=> Sun Aug 27 23:18:25 PDT 2006
|
|
10
|
+
#
|
|
11
|
+
# Chronic.parse('tomorrow')
|
|
12
|
+
# #=> Mon Aug 28 12:00:00 PDT 2006
|
|
13
|
+
#
|
|
14
|
+
# Chronic.parse('monday', :context => :past)
|
|
15
|
+
# #=> 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
|
|
10
30
|
module Chronic
|
|
11
|
-
VERSION = "0.4.
|
|
31
|
+
VERSION = "0.4.3"
|
|
12
32
|
|
|
13
33
|
class << self
|
|
34
|
+
|
|
35
|
+
# @return [Boolean] true when debug mode is enabled
|
|
14
36
|
attr_accessor :debug
|
|
37
|
+
|
|
38
|
+
# @example
|
|
39
|
+
# require 'chronic'
|
|
40
|
+
# require 'active_support/time'
|
|
41
|
+
#
|
|
42
|
+
# Time.zone = 'UTC'
|
|
43
|
+
# Chronic.time_class = Time.zone
|
|
44
|
+
# Chronic.parse('June 15 2006 at 5:54 AM')
|
|
45
|
+
# # => Thu, 15 Jun 2006 05:45:00 UTC +00:00
|
|
46
|
+
#
|
|
47
|
+
# @return [Time] The time class Chronic uses internally
|
|
15
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
|
|
16
61
|
end
|
|
17
62
|
|
|
18
63
|
self.debug = false
|
|
19
64
|
self.time_class = Time
|
|
20
65
|
end
|
|
21
66
|
|
|
22
|
-
require 'time'
|
|
23
|
-
require 'date'
|
|
24
|
-
|
|
25
67
|
require 'chronic/chronic'
|
|
26
68
|
require 'chronic/handlers'
|
|
27
69
|
require 'chronic/mini_date'
|
|
28
70
|
require 'chronic/tag'
|
|
29
71
|
require 'chronic/span'
|
|
30
72
|
require 'chronic/token'
|
|
73
|
+
require 'chronic/grabber'
|
|
74
|
+
require 'chronic/pointer'
|
|
75
|
+
require 'chronic/scalar'
|
|
76
|
+
require 'chronic/ordinal'
|
|
77
|
+
require 'chronic/separator'
|
|
78
|
+
require 'chronic/time_zone'
|
|
79
|
+
require 'chronic/numerizer'
|
|
31
80
|
|
|
32
81
|
require 'chronic/repeater'
|
|
33
82
|
require 'chronic/repeaters/repeater_year'
|
|
@@ -47,42 +96,6 @@ require 'chronic/repeaters/repeater_minute'
|
|
|
47
96
|
require 'chronic/repeaters/repeater_second'
|
|
48
97
|
require 'chronic/repeaters/repeater_time'
|
|
49
98
|
|
|
50
|
-
require 'chronic/grabber'
|
|
51
|
-
require 'chronic/pointer'
|
|
52
|
-
require 'chronic/scalar'
|
|
53
|
-
require 'chronic/ordinal'
|
|
54
|
-
require 'chronic/separator'
|
|
55
|
-
require 'chronic/time_zone'
|
|
56
|
-
|
|
57
|
-
require 'chronic/numerizer'
|
|
58
|
-
|
|
59
|
-
# class Time
|
|
60
|
-
# def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
|
|
61
|
-
# # extra_seconds = second > 60 ? second - 60 : 0
|
|
62
|
-
# # extra_minutes = minute > 59 ? minute - 59 : 0
|
|
63
|
-
# # extra_hours = hour > 23 ? hour - 23 : 0
|
|
64
|
-
# # extra_days = day >
|
|
65
|
-
#
|
|
66
|
-
# if month > 12
|
|
67
|
-
# if month % 12 == 0
|
|
68
|
-
# year += (month - 12) / 12
|
|
69
|
-
# month = 12
|
|
70
|
-
# else
|
|
71
|
-
# year += month / 12
|
|
72
|
-
# month = month % 12
|
|
73
|
-
# end
|
|
74
|
-
# end
|
|
75
|
-
#
|
|
76
|
-
# base = Time.local(year, month)
|
|
77
|
-
# puts base
|
|
78
|
-
# offset = ((day - 1) * 24 * 60 * 60) + (hour * 60 * 60) + (minute * 60) + second
|
|
79
|
-
# puts offset.to_s
|
|
80
|
-
# date = base + offset
|
|
81
|
-
# puts date
|
|
82
|
-
# date
|
|
83
|
-
# end
|
|
84
|
-
# end
|
|
85
|
-
|
|
86
99
|
class Time
|
|
87
100
|
def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
|
|
88
101
|
if second >= 60
|
data/test/test_Chronic.rb
CHANGED
|
@@ -21,7 +21,7 @@ class TestChronic < Test::Unit::TestCase
|
|
|
21
21
|
|
|
22
22
|
assert_equal :morning, tokens[1].tags[0].type
|
|
23
23
|
|
|
24
|
-
tokens = Chronic.dealias_and_disambiguate_times(tokens, {})
|
|
24
|
+
tokens = Chronic::Handlers.dealias_and_disambiguate_times(tokens, {})
|
|
25
25
|
|
|
26
26
|
assert_equal :am, tokens[1].tags[0].type
|
|
27
27
|
assert_equal 2, tokens.size
|
|
@@ -34,7 +34,7 @@ class TestChronic < Test::Unit::TestCase
|
|
|
34
34
|
|
|
35
35
|
assert_equal :morning, tokens[1].tags[0].type
|
|
36
36
|
|
|
37
|
-
tokens = Chronic.dealias_and_disambiguate_times(tokens, {})
|
|
37
|
+
tokens = Chronic::Handlers.dealias_and_disambiguate_times(tokens, {})
|
|
38
38
|
|
|
39
39
|
assert_equal :morning, tokens[1].tags[0].type
|
|
40
40
|
assert_equal 2, tokens.size
|
|
@@ -51,4 +51,54 @@ class TestChronic < Test::Unit::TestCase
|
|
|
51
51
|
assert_equal Time.local(2006, 11, 16), Chronic.guess(span)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def test_now
|
|
55
|
+
Chronic.parse('now', :now => Time.local(2006, 01))
|
|
56
|
+
assert_equal Time.local(2006, 01), Chronic.now
|
|
57
|
+
|
|
58
|
+
Chronic.parse('now', :now => Time.local(2007, 01))
|
|
59
|
+
assert_equal Time.local(2007, 01), Chronic.now
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_endian_definitions
|
|
63
|
+
# middle, little
|
|
64
|
+
endians = [
|
|
65
|
+
Chronic::Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
|
|
66
|
+
Chronic::Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
assert_equal endians, Chronic.definitions[:endian]
|
|
70
|
+
|
|
71
|
+
defs = Chronic.definitions(:endian_precedence => :little)
|
|
72
|
+
assert_equal endians.reverse, defs[:endian]
|
|
73
|
+
|
|
74
|
+
defs = Chronic.definitions(:endian_precedence => [:little, :middle])
|
|
75
|
+
assert_equal endians.reverse, defs[:endian]
|
|
76
|
+
|
|
77
|
+
assert_raises(Chronic::InvalidArgumentException) do
|
|
78
|
+
Chronic.definitions(:endian_precedence => :invalid)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_passing_options
|
|
83
|
+
assert_raises(Chronic::InvalidArgumentException) do
|
|
84
|
+
Chronic.parse('now', :invalid => :option)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
assert_raises(Chronic::InvalidArgumentException) do
|
|
88
|
+
Chronic.parse('now', :context => :invalid_context)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_debug
|
|
93
|
+
require 'stringio'
|
|
94
|
+
$stdout = StringIO.new
|
|
95
|
+
Chronic.debug = true
|
|
96
|
+
|
|
97
|
+
Chronic.parse 'now'
|
|
98
|
+
assert $stdout.string.include?('this(grabber-this)')
|
|
99
|
+
ensure
|
|
100
|
+
$stdout = STDOUT
|
|
101
|
+
Chronic.debug = false
|
|
102
|
+
end
|
|
103
|
+
|
|
54
104
|
end
|
data/test/test_RepeaterMonth.rb
CHANGED
|
@@ -23,6 +23,10 @@ class TestRepeaterMonth < Test::Unit::TestCase
|
|
|
23
23
|
|
|
24
24
|
time = Chronic::RepeaterMonth.new(:month).offset_by(@now, 10, :past)
|
|
25
25
|
assert_equal Time.local(2005, 10, 16, 14), time
|
|
26
|
+
|
|
27
|
+
time = Chronic::RepeaterMonth.new(:month).offset_by(Time.local(2010, 3, 29), 1, :past)
|
|
28
|
+
assert_equal 2, time.month
|
|
29
|
+
assert_equal 28, time.day
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def test_offset
|
data/test/test_parsing.rb
CHANGED
|
@@ -274,6 +274,12 @@ class TestParsing < Test::Unit::TestCase
|
|
|
274
274
|
time = parse_now("13:45")
|
|
275
275
|
assert_equal Time.local(2006, 8, 17, 13, 45), time
|
|
276
276
|
|
|
277
|
+
time = parse_now("1:01pm")
|
|
278
|
+
assert_equal Time.local(2006, 8, 16, 13, 01), time
|
|
279
|
+
|
|
280
|
+
time = parse_now("2:01pm")
|
|
281
|
+
assert_equal Time.local(2006, 8, 16, 14, 01), time
|
|
282
|
+
|
|
277
283
|
time = parse_now("november")
|
|
278
284
|
assert_equal Time.local(2006, 11, 16), time
|
|
279
285
|
end
|
metadata
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chronic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
hash: 9
|
|
5
|
+
prerelease: false
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 4
|
|
9
|
+
- 3
|
|
10
|
+
version: 0.4.3
|
|
6
11
|
platform: ruby
|
|
7
12
|
authors:
|
|
8
13
|
- Tom Preston-Werner
|
|
@@ -11,7 +16,8 @@ autorequire:
|
|
|
11
16
|
bindir: bin
|
|
12
17
|
cert_chain: []
|
|
13
18
|
|
|
14
|
-
date: 2011-06-
|
|
19
|
+
date: 2011-06-08 00:00:00 +01:00
|
|
20
|
+
default_executable:
|
|
15
21
|
dependencies: []
|
|
16
22
|
|
|
17
23
|
description: Chronic is a natural language date/time parser written in pure Ruby.
|
|
@@ -27,6 +33,8 @@ extra_rdoc_files:
|
|
|
27
33
|
- HISTORY.md
|
|
28
34
|
- LICENSE
|
|
29
35
|
files:
|
|
36
|
+
- .gitignore
|
|
37
|
+
- .yardopts
|
|
30
38
|
- HISTORY.md
|
|
31
39
|
- LICENSE
|
|
32
40
|
- Manifest.txt
|
|
@@ -86,6 +94,7 @@ files:
|
|
|
86
94
|
- test/test_Time.rb
|
|
87
95
|
- test/test_Token.rb
|
|
88
96
|
- test/test_parsing.rb
|
|
97
|
+
has_rdoc: true
|
|
89
98
|
homepage: http://github.com/mojombo/chronic
|
|
90
99
|
licenses: []
|
|
91
100
|
|
|
@@ -99,21 +108,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
99
108
|
requirements:
|
|
100
109
|
- - ">="
|
|
101
110
|
- !ruby/object:Gem::Version
|
|
111
|
+
hash: 3
|
|
112
|
+
segments:
|
|
113
|
+
- 0
|
|
102
114
|
version: "0"
|
|
103
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
116
|
none: false
|
|
105
117
|
requirements:
|
|
106
118
|
- - ">="
|
|
107
119
|
- !ruby/object:Gem::Version
|
|
120
|
+
hash: 3
|
|
121
|
+
segments:
|
|
122
|
+
- 0
|
|
108
123
|
version: "0"
|
|
109
124
|
requirements: []
|
|
110
125
|
|
|
111
126
|
rubyforge_project: chronic
|
|
112
|
-
rubygems_version: 1.
|
|
127
|
+
rubygems_version: 1.3.7
|
|
113
128
|
signing_key:
|
|
114
129
|
specification_version: 3
|
|
115
130
|
summary: Natural language date/time parsing.
|
|
116
131
|
test_files:
|
|
132
|
+
- test/helper.rb
|
|
117
133
|
- test/test_Chronic.rb
|
|
118
134
|
- test/test_DaylightSavings.rb
|
|
119
135
|
- test/test_Handler.rb
|