kronos 0.1.3 → 0.1.4
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/README.md +50 -11
- data/VERSION +1 -1
- data/kronos.gemspec +10 -6
- data/lib/kronos.rb +88 -0
- data/spec/compare_spec.rb +229 -0
- data/spec/valid_spec.rb +29 -0
- metadata +24 -9
data/README.md
CHANGED
@@ -55,20 +55,59 @@ In contrast, other date parsing libraries, such as [Chronic](http://github.com/m
|
|
55
55
|
|
56
56
|
Kronos is currently implemented as a thin wrapper over [ParseDate](http://ruby-doc.org/stdlib/libdoc/parsedate/rdoc/index.html).
|
57
57
|
|
58
|
-
##
|
58
|
+
## Date Comparisons
|
59
59
|
|
60
|
-
|
60
|
+
Kronos handles date-related comparisons more intelligently.
|
61
61
|
|
62
|
-
|
62
|
+
Many Ruby date libraries make the assumption that you are specifying a point (i.e. a particular date), not an interval (such as an entire month or year). Kronos, on the other hand, lets you specify dates that are intervals:
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
k_1973 = Kronos.parse("1973")
|
65
|
+
k_1974 = Kronos.parse("1974")
|
66
|
+
k_march_1974 = Kronos.parse("March 1974")
|
67
|
+
|
68
|
+
With Kronos, you can compare date objects as follows:
|
69
|
+
|
70
|
+
k_1973 < k_1973 # => true
|
71
|
+
k_1973 < k_march_1974 # => true
|
72
|
+
|
73
|
+
### A Note about Kronos Comparison Operators
|
74
|
+
|
75
|
+
Kronos interprets "<" as "Does the date interval on the left occur completely before the date interval on the right?" In other words, if there is overlap, the result will be false.
|
76
|
+
|
77
|
+
Here's an example. If you ask "Does the year 1974 came before March 1974?" a careful response might be: "Actually, part of it comes before and part of it comes after. Your question does not really make sense because March 1974 is contained within the year 1974."
|
78
|
+
|
79
|
+
Because of this, Konos comparison operators (<, ==, >) behave a little bit differently for Kronos objects than for, say, integers. Given any two integers m and n, you can be sure that one of the operators holds. For example:
|
80
|
+
|
81
|
+
m = 1
|
82
|
+
n = 2
|
83
|
+
m < n # => true
|
84
|
+
m == n # => false
|
85
|
+
m > n # => false
|
86
|
+
|
87
|
+
However, given two Kronos objects k1 and k2 you cannot guarantee that one of the operators will hold. For example:
|
88
|
+
|
89
|
+
k_1974 < k_march_1974 # => false
|
90
|
+
k_1973 == k_march_1974 # => false
|
91
|
+
k_1974 > k_march_1974 # => false
|
92
|
+
|
93
|
+
Since the two dates are unequal but overlap, Kronos will always return false.
|
94
|
+
|
95
|
+
### Future Work
|
96
|
+
|
97
|
+
I plan to implement the `in?` method as follows:
|
98
|
+
|
99
|
+
k_march_1974.in?(k_1974) # => true
|
100
|
+
k_1974.in?(k_march_1974) # => false
|
101
|
+
|
102
|
+
## History
|
103
|
+
|
104
|
+
We import a lot of data from government Web sites as part of our work at the Sunlight Labs (the technical arm of the Sunlight Foundation). I did not want to store date-related information in a way that made it seem more precise than it really was, so I wrote this little library. -David
|
105
|
+
|
106
|
+
## Contributors
|
107
|
+
|
108
|
+
David James (djsun)
|
109
|
+
Eric Mill (klondike)
|
71
110
|
|
72
111
|
## Feedback
|
73
112
|
|
74
|
-
|
113
|
+
We would appreciate your feedback. Thanks!
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/kronos.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{kronos}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David James"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-03-09}
|
13
13
|
s.description = %q{Kronos provides flexible date parsing. Currently just a thin layer on top of ParseDate.}
|
14
14
|
s.email = %q{djames@sunlightfoundation.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,18 +25,22 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"kronos.gemspec",
|
27
27
|
"lib/kronos.rb",
|
28
|
+
"spec/compare_spec.rb",
|
28
29
|
"spec/kronos_spec.rb",
|
29
30
|
"spec/spec.opts",
|
30
|
-
"spec/spec_helper.rb"
|
31
|
+
"spec/spec_helper.rb",
|
32
|
+
"spec/valid_spec.rb"
|
31
33
|
]
|
32
34
|
s.homepage = %q{http://github.com/djsun/kronos}
|
33
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
34
36
|
s.require_paths = ["lib"]
|
35
|
-
s.rubygems_version = %q{1.3.
|
37
|
+
s.rubygems_version = %q{1.3.6}
|
36
38
|
s.summary = %q{Simple and flexible date parsing.}
|
37
39
|
s.test_files = [
|
38
|
-
"spec/
|
39
|
-
"spec/
|
40
|
+
"spec/compare_spec.rb",
|
41
|
+
"spec/kronos_spec.rb",
|
42
|
+
"spec/spec_helper.rb",
|
43
|
+
"spec/valid_spec.rb"
|
40
44
|
]
|
41
45
|
|
42
46
|
if s.respond_to? :specification_version then
|
data/lib/kronos.rb
CHANGED
@@ -29,6 +29,94 @@ class Kronos
|
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
32
|
+
def valid?
|
33
|
+
if day
|
34
|
+
return false unless month && year
|
35
|
+
end
|
36
|
+
if month
|
37
|
+
return false unless year
|
38
|
+
end
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def <(other)
|
43
|
+
if !self.year || !other.year
|
44
|
+
false
|
45
|
+
elsif self.year < other.year
|
46
|
+
true
|
47
|
+
elsif self.year > other.year
|
48
|
+
false
|
49
|
+
elsif self.year == other.year
|
50
|
+
if !self.month || !other.month
|
51
|
+
false
|
52
|
+
elsif self.month < other.month
|
53
|
+
true
|
54
|
+
elsif self.month > other.month
|
55
|
+
false
|
56
|
+
elsif self.month == other.month
|
57
|
+
if !self.day || !other.day
|
58
|
+
false
|
59
|
+
elsif self.day < other.day
|
60
|
+
true
|
61
|
+
elsif self.day > other.day
|
62
|
+
false
|
63
|
+
elsif self.day == other.day
|
64
|
+
false
|
65
|
+
else
|
66
|
+
raise "Unexpected"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
raise "Unexpected"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def <=(other)
|
75
|
+
(self < other) || (self == other)
|
76
|
+
end
|
77
|
+
|
78
|
+
def ==(other)
|
79
|
+
self.year == other.year &&
|
80
|
+
self.month == other.month &&
|
81
|
+
self.day == other.day
|
82
|
+
end
|
83
|
+
|
84
|
+
def >=(other)
|
85
|
+
(self > other) || (self == other)
|
86
|
+
end
|
87
|
+
|
88
|
+
def >(other)
|
89
|
+
if !self.year || !other.year
|
90
|
+
false
|
91
|
+
elsif self.year < other.year
|
92
|
+
false
|
93
|
+
elsif self.year > other.year
|
94
|
+
true
|
95
|
+
elsif self.year == other.year
|
96
|
+
if !self.month || !other.month
|
97
|
+
false
|
98
|
+
elsif self.month < other.month
|
99
|
+
false
|
100
|
+
elsif self.month > other.month
|
101
|
+
true
|
102
|
+
elsif self.month == other.month
|
103
|
+
if !self.day || !other.day
|
104
|
+
false
|
105
|
+
elsif self.day < other.day
|
106
|
+
false
|
107
|
+
elsif self.day > other.day
|
108
|
+
true
|
109
|
+
elsif self.day == other.day
|
110
|
+
false
|
111
|
+
else
|
112
|
+
raise "Unexpected"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
else
|
116
|
+
raise "Unexpected"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
32
120
|
def to_hash
|
33
121
|
h = {}
|
34
122
|
h['year'] = year if year
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Kronos Comparisons" do
|
4
|
+
|
5
|
+
def new_kronos(year=nil, month=nil, day=nil)
|
6
|
+
k = Kronos.new
|
7
|
+
k.year = year if year
|
8
|
+
k.month = month if month
|
9
|
+
k.day = day if day
|
10
|
+
k
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "2005 vs 2005" do
|
14
|
+
before do
|
15
|
+
@k1 = new_kronos(2005)
|
16
|
+
@k2 = new_kronos(2005)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should not be <" do
|
20
|
+
(@k1 < @k2).should == false
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be <=" do
|
24
|
+
(@k1 <= @k2).should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be ==" do
|
28
|
+
(@k1 == @k2).should == true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be >=" do
|
32
|
+
(@k1 >= @k2).should == true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not be >" do
|
36
|
+
(@k1 > @k2).should == false
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "2005 vs 2006" do
|
42
|
+
before do
|
43
|
+
@k1 = new_kronos(2005)
|
44
|
+
@k2 = new_kronos(2006)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be <" do
|
48
|
+
(@k1 < @k2).should == true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should be <=" do
|
52
|
+
(@k1 <= @k2).should == true
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not be ==" do
|
56
|
+
(@k1 == @k2).should == false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not be >" do
|
60
|
+
(@k1 > @k2).should == false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not be >=" do
|
64
|
+
(@k1 >= @k2).should == false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "March 2005 vs 2006" do
|
69
|
+
before do
|
70
|
+
@k1 = new_kronos(2005, 3)
|
71
|
+
@k2 = new_kronos(2006)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be <" do
|
75
|
+
(@k1 < @k2).should == true
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should be <=" do
|
79
|
+
(@k1 <= @k2).should == true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not be ==" do
|
83
|
+
(@k1 == @k2).should == false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not be >" do
|
87
|
+
(@k1 > @k2).should == false
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not be >=" do
|
91
|
+
(@k1 >= @k2).should == false
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "April 2000 vs May 2000" do
|
96
|
+
before do
|
97
|
+
@k1 = new_kronos(2000, 4)
|
98
|
+
@k2 = new_kronos(2000, 5)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be <" do
|
102
|
+
(@k1 < @k2).should == true
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should be <=" do
|
106
|
+
(@k1 <= @k2).should == true
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not be ==" do
|
110
|
+
(@k1 == @k2).should == false
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should not be >" do
|
114
|
+
(@k1 > @k2).should == false
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should not be >=" do
|
118
|
+
(@k1 >= @k2).should == false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "April 10, 2000 vs May 1, 2000" do
|
123
|
+
before do
|
124
|
+
@k1 = new_kronos(2000, 4, 10)
|
125
|
+
@k2 = new_kronos(2000, 5, 1)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should be <" do
|
129
|
+
(@k1 < @k2).should == true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should be <=" do
|
133
|
+
(@k1 <= @k2).should == true
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should not be ==" do
|
137
|
+
(@k1 == @k2).should == false
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should not be >" do
|
141
|
+
(@k1 > @k2).should == false
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should not be >=" do
|
145
|
+
(@k1 >= @k2).should == false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "April 10, 2000 vs May 2000" do
|
150
|
+
before do
|
151
|
+
@k1 = new_kronos(2000, 4, 10)
|
152
|
+
@k2 = new_kronos(2000, 5)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be <" do
|
156
|
+
(@k1 < @k2).should == true
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should be <=" do
|
160
|
+
(@k1 <= @k2).should == true
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should not be ==" do
|
164
|
+
(@k1 == @k2).should == false
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should not be >" do
|
168
|
+
(@k1 > @k2).should == false
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should not be >=" do
|
172
|
+
(@k1 >= @k2).should == false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "April 10, 2000 vs April 8, 2000" do
|
177
|
+
before do
|
178
|
+
@k1 = new_kronos(2000, 4, 10)
|
179
|
+
@k2 = new_kronos(2000, 4, 8)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should not be <" do
|
183
|
+
(@k1 < @k2).should == false
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should not be <=" do
|
187
|
+
(@k1 <= @k2).should == false
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should not be ==" do
|
191
|
+
(@k1 == @k2).should == false
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should be >" do
|
195
|
+
(@k1 > @k2).should == true
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should be >=" do
|
199
|
+
(@k1 >= @k2).should == true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "(blank) vs 2000" do
|
204
|
+
before do
|
205
|
+
@k1 = new_kronos()
|
206
|
+
@k2 = new_kronos(2000)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not be <" do
|
210
|
+
(@k1 < @k2).should == false
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not be <=" do
|
214
|
+
(@k1 <= @k2).should == false
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should not be ==" do
|
218
|
+
(@k1 == @k2).should == false
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should not be >" do
|
222
|
+
(@k1 > @k2).should == false
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should not be >=" do
|
226
|
+
(@k1 >= @k2).should == false
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
data/spec/valid_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Kronos Comparisons" do
|
4
|
+
|
5
|
+
def new_kronos(year=nil, month=nil, day=nil)
|
6
|
+
k = Kronos.new
|
7
|
+
k.year = year if year
|
8
|
+
k.month = month if month
|
9
|
+
k.day = day if day
|
10
|
+
k
|
11
|
+
end
|
12
|
+
|
13
|
+
it "year only is valid" do
|
14
|
+
new_kronos(2005).valid?.should == true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "month and year is valid" do
|
18
|
+
new_kronos(2005, 8).valid?.should == true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "month, day, and year is valid" do
|
22
|
+
new_kronos(2005, 8, 22).valid?.should == true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "day and year is invalid" do
|
26
|
+
new_kronos(2005, nil, 22).valid?.should == false
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kronos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 4
|
9
|
+
version: 0.1.4
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- David James
|
@@ -9,19 +14,23 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-03-09 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
23
31
|
version: 1.2.9
|
24
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
25
34
|
description: Kronos provides flexible date parsing. Currently just a thin layer on top of ParseDate.
|
26
35
|
email: djames@sunlightfoundation.com
|
27
36
|
executables: []
|
@@ -40,9 +49,11 @@ files:
|
|
40
49
|
- VERSION
|
41
50
|
- kronos.gemspec
|
42
51
|
- lib/kronos.rb
|
52
|
+
- spec/compare_spec.rb
|
43
53
|
- spec/kronos_spec.rb
|
44
54
|
- spec/spec.opts
|
45
55
|
- spec/spec_helper.rb
|
56
|
+
- spec/valid_spec.rb
|
46
57
|
has_rdoc: true
|
47
58
|
homepage: http://github.com/djsun/kronos
|
48
59
|
licenses: []
|
@@ -56,21 +67,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
67
|
requirements:
|
57
68
|
- - ">="
|
58
69
|
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
59
72
|
version: "0"
|
60
|
-
version:
|
61
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
74
|
requirements:
|
63
75
|
- - ">="
|
64
76
|
- !ruby/object:Gem::Version
|
77
|
+
segments:
|
78
|
+
- 0
|
65
79
|
version: "0"
|
66
|
-
version:
|
67
80
|
requirements: []
|
68
81
|
|
69
82
|
rubyforge_project:
|
70
|
-
rubygems_version: 1.3.
|
83
|
+
rubygems_version: 1.3.6
|
71
84
|
signing_key:
|
72
85
|
specification_version: 3
|
73
86
|
summary: Simple and flexible date parsing.
|
74
87
|
test_files:
|
88
|
+
- spec/compare_spec.rb
|
75
89
|
- spec/kronos_spec.rb
|
76
90
|
- spec/spec_helper.rb
|
91
|
+
- spec/valid_spec.rb
|