edtf 3.3.0 → 4.0.0
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/README.md +143 -117
- data/lib/edtf/date.rb +39 -2
- data/lib/edtf/epoch.rb +3 -1
- data/lib/edtf/interval.rb +40 -15
- data/lib/edtf/parser.rb +33 -33
- data/lib/edtf/parser.y +32 -32
- data/lib/edtf/season.rb +10 -2
- data/lib/edtf/set.rb +15 -1
- data/lib/edtf/uncertainty.rb +7 -8
- data/lib/edtf/version.rb +1 -1
- metadata +26 -57
- data/.github/workflows/ci.yml +0 -44
- data/.gitignore +0 -8
- data/.rspec +0 -3
- data/.simplecov +0 -19
- data/Gemfile +0 -20
- data/Rakefile +0 -41
- data/cucumber.yml +0 -1
- data/edtf.gemspec +0 -29
- data/features/parser/date_times.feature +0 -41
- data/features/parser/dates.feature +0 -89
- data/features/parser/intervals.feature +0 -18
- data/features/parser/precision.feature +0 -14
- data/features/parser/uncertain_or_approximate.feature +0 -129
- data/features/parser/unspecified.feature +0 -34
- data/features/print/level_0_edtf.feature +0 -79
- data/features/print/level_1_edtf.feature +0 -137
- data/features/print/level_2_edtf.feature +0 -39
- data/features/print/uncertain_or_approximate.feature +0 -131
- data/features/step_definitions/edtf_steps.rb +0 -150
- data/features/support/env.rb +0 -13
- data/spec/edtf/date_spec.rb +0 -245
- data/spec/edtf/epoch_spec.rb +0 -88
- data/spec/edtf/interval_spec.rb +0 -308
- data/spec/edtf/parser_spec.rb +0 -427
- data/spec/edtf/season_spec.rb +0 -111
- data/spec/edtf/set_spec.rb +0 -107
- data/spec/edtf/uncertainty_spec.rb +0 -296
- data/spec/spec_helper.rb +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68cf5a59b655ee503dfda487dd719422299c40ee1744baeb93605b5b08bd0c9f
|
|
4
|
+
data.tar.gz: 2b8e4a4e41c46f9607057c2b61720d3fce35acae2afa73ea112ff3bfdc03dc5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34e2bf30004ba2eb3389d69fd9244cff29ddcf915e477e894b513116365efb0862585d2fa078786d5f40c22cfbddfec23d26a361886be0a78013f1b4457e0b93
|
|
7
|
+
data.tar.gz: fa871f182f1ec791e36946c0a8a5127323c6b4da1aa6915b625f180a2e0698d586f6452d4d969f2d9f4345195838a92a4ee6414068354334f79a27ceb6fc0000
|
data/README.md
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
EDTF-Ruby
|
|
2
2
|
=========
|
|
3
3
|
[](https://github.com/inukshuk/edtf-ruby/actions/workflows/ci.yml)
|
|
4
|
-
[](https://coveralls.io/github/inukshuk/edtf-ruby?branch=main)
|
|
5
4
|
|
|
6
|
-
EDTF-Ruby comprises a parser and an API implementation
|
|
7
|
-
Date/Time Format standard](
|
|
5
|
+
EDTF-Ruby comprises a parser and an API implementation
|
|
6
|
+
of the [Extended Date/Time Format standard](https://www.loc.gov/standards/datetime/).
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
Compatibility
|
|
11
10
|
-------------
|
|
12
11
|
EDTF-Ruby parser implements all levels and features of the EDTF specification
|
|
13
|
-
(version September 16, 2011).
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
extensions are currently listed as a dependency,
|
|
27
|
-
|
|
12
|
+
(version September 16, 2011).
|
|
13
|
+
With the following known caveats:
|
|
14
|
+
|
|
15
|
+
* In the latest revision of the EDTF specification
|
|
16
|
+
alternative versions of partial uncertain/approximate strings were introduced
|
|
17
|
+
(with or without nested parentheses);
|
|
18
|
+
EDTF-Ruby currently uses the version that tries to reduce parentheses for printing
|
|
19
|
+
as we find that one easier to read;
|
|
20
|
+
the parser accepts all valid dates using this approach,
|
|
21
|
+
plus some dates using nested expressions
|
|
22
|
+
(the parser will not accept some of the more complex examples, though).
|
|
23
|
+
|
|
24
|
+
EDTF-Ruby is tested on Ruby 3.3 and later, and on JRuby.
|
|
25
|
+
Active Support's date extensions are currently listed as a dependency,
|
|
26
|
+
because of many functional overlaps
|
|
27
|
+
(versions 3.x through 8.x are supported).
|
|
28
28
|
|
|
29
29
|
### ISO 8601-2
|
|
30
30
|
|
|
31
|
-
A variation of EDTF has been adopted by the ISO 8601-2 standard.
|
|
32
|
-
does not support this new version of EDTF yet,
|
|
31
|
+
A variation of EDTF has been adopted by the ISO 8601-2 standard.
|
|
32
|
+
EDTF-Ruby does not support this new version of EDTF yet,
|
|
33
|
+
but if you are curious,
|
|
33
34
|
[EDTF.js](https://github.com/inukshuk/edtf.js), an ES6 implementation
|
|
34
35
|
is already available.
|
|
35
36
|
|
|
@@ -37,23 +38,28 @@ Quickstart
|
|
|
37
38
|
----------
|
|
38
39
|
EDTF Ruby is implemented as an extension to the regular Ruby date/time classes.
|
|
39
40
|
You can parse EDTF strings either using `Date.edtf` or `EDTF.parse`
|
|
40
|
-
(both methods come with an alternative bang! version,
|
|
41
|
-
if the string cannot be parsed
|
|
42
|
-
|
|
41
|
+
(both methods come with an alternative bang! version,
|
|
42
|
+
that will raise an error if the string cannot be parsed
|
|
43
|
+
instead of silently returning nil);
|
|
44
|
+
if given a valid EDTF string
|
|
45
|
+
the return value will either be an (extended) `Date`,
|
|
43
46
|
`EDTF::Interval`, `EDTF::Set`, `EDTF::Epoch` or `EDTF::Season` instance.
|
|
44
47
|
|
|
45
|
-
Given any of these instances,
|
|
46
|
-
using the `#edtf` method.
|
|
48
|
+
Given any of these instances,
|
|
49
|
+
you can print the corresponding EDTF string using the `#edtf` method.
|
|
47
50
|
|
|
48
51
|
### Dates
|
|
49
52
|
|
|
50
|
-
Most of the EDTF features deal with dates;
|
|
51
|
-
extending Active Support's version
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
Most of the EDTF features deal with dates;
|
|
54
|
+
EDTF-Ruby implements these by extending Active Support's version
|
|
55
|
+
of the regular Ruby Date class.
|
|
56
|
+
The library intends to be transparent to Ruby's regular API,
|
|
57
|
+
i.e., every Date instance should act as you would normally expect
|
|
58
|
+
but provides additional functionality.
|
|
54
59
|
|
|
55
|
-
Most
|
|
56
|
-
subtle difference that determines how many other methods work.
|
|
60
|
+
Most notably, EDTF dates come in day, month, or year precision.
|
|
61
|
+
This is a subtle difference that determines how many other methods work.
|
|
62
|
+
For instance:
|
|
57
63
|
|
|
58
64
|
> Date.today.precision
|
|
59
65
|
=> :day
|
|
@@ -64,16 +70,18 @@ subtle difference that determines how many other methods work. For instance:
|
|
|
64
70
|
> Date.today.month_precision!.succ
|
|
65
71
|
=> Sat, 10 Dec 2011
|
|
66
72
|
|
|
67
|
-
As you can see, dates have day precision by default;
|
|
68
|
-
precision to month, however,
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
As you can see, dates have day precision by default;
|
|
74
|
+
after setting the date's precision to month, however,
|
|
75
|
+
the natural successor is not the next day,
|
|
76
|
+
but a day a month from now.
|
|
77
|
+
Always keep precision in mind when comparing dates, too:
|
|
71
78
|
|
|
72
79
|
> Date.new(1966).year_precision! == Date.new(1966)
|
|
73
80
|
=> false
|
|
74
81
|
|
|
75
|
-
The year 1966 is not equal to the January 1st, 1966.
|
|
76
|
-
|
|
82
|
+
The year 1966 is not equal to the January 1st, 1966.
|
|
83
|
+
You can set a date's precision directly,
|
|
84
|
+
or else use the dedicated bang! methods:
|
|
77
85
|
|
|
78
86
|
> d = Date.new(1993)
|
|
79
87
|
> d.day_precision? # -> true
|
|
@@ -88,35 +96,39 @@ precision directly, or else use the dedicated bang! methods:
|
|
|
88
96
|
> d.day_precision? # -> false
|
|
89
97
|
> d.year_precision? # -> true
|
|
90
98
|
|
|
91
|
-
In the examples above, you also see that the `#edtf` method
|
|
92
|
-
different string depending on the date's current precision.
|
|
99
|
+
In the examples above, you also see that the `#edtf` method
|
|
100
|
+
will print a different string depending on the date's current precision.
|
|
93
101
|
|
|
94
|
-
The second important extension is that dates can be uncertain and or
|
|
95
|
-
|
|
102
|
+
The second important extension is that dates can be uncertain and or approximate.
|
|
103
|
+
The distinction between the two may seem somewhat contrived,
|
|
96
104
|
but we have come to understand it as follows:
|
|
97
105
|
|
|
98
|
-
Assume you take a history exam
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
Assume you take a history exam
|
|
107
|
+
and have to answer one of those dreaded questions
|
|
108
|
+
that require you to say exactly in what year a certain event happened;
|
|
109
|
+
you studied hard, but all of a sudden you are *uncertain*:
|
|
110
|
+
was that the year 1683 or was it 1638?
|
|
111
|
+
This is what uncertainty is in the parlance of EDTF:
|
|
112
|
+
in fact, you would write it just like that "1638?".
|
|
113
|
+
|
|
114
|
+
Approximate dates are similar but slightly different.
|
|
115
|
+
Let's say you want to tell a story about something that happened to you one winter;
|
|
116
|
+
you don't recall the exact date,
|
|
117
|
+
but you know it must have been sometime between Christmas and New Year's.
|
|
118
|
+
Come to think of it, you don't remember the year either,
|
|
119
|
+
but you must have been around ten years old.
|
|
120
|
+
Using EDTF, you could write something like "1993~-12-(27)~":
|
|
121
|
+
this indicates that both the year and the day are approximations:
|
|
122
|
+
perhaps the day is not the 27th but it is somewhere close.
|
|
123
|
+
|
|
124
|
+
This is the main difference between uncertain and approximate in EDTF
|
|
125
|
+
(in our opinion at least):
|
|
126
|
+
approximate always means close to the actual number,
|
|
127
|
+
whilst uncertain could be something completely different
|
|
116
128
|
(just as there is a large temporal distance between 1638 and 1683).
|
|
117
129
|
|
|
118
|
-
Here are a few examples of how you can access
|
|
119
|
-
state of dates in Ruby:
|
|
130
|
+
Here are a few examples of how you can access
|
|
131
|
+
the uncertain/approximate state of dates in Ruby:
|
|
120
132
|
|
|
121
133
|
> d = Date.edtf('1984?')
|
|
122
134
|
> d.uncertain?
|
|
@@ -133,12 +145,11 @@ state of dates in Ruby:
|
|
|
133
145
|
> d.edtf
|
|
134
146
|
=> "1984?-01~"
|
|
135
147
|
|
|
136
|
-
As you can see above, you can use the bang! methods to set individual date
|
|
137
|
-
parts.
|
|
148
|
+
As you can see above, you can use the bang! methods to set individual date parts.
|
|
138
149
|
|
|
139
|
-
In addition, EDTF supports *unspecified* date parts.
|
|
140
|
-
for both the draft and finalized EDTF specifications,
|
|
141
|
-
requirements of the final specification:
|
|
150
|
+
In addition, EDTF supports *unspecified* date parts.
|
|
151
|
+
EDTF-Ruby provides parsing for both the draft and finalized EDTF specifications,
|
|
152
|
+
with output meeting the requirements of the final specification:
|
|
142
153
|
|
|
143
154
|
> d = Date.edtf('1999-03-XX')
|
|
144
155
|
> d.unspecified?
|
|
@@ -155,8 +166,9 @@ requirements of the final specification:
|
|
|
155
166
|
> draft_d.edtf
|
|
156
167
|
=> "1999-03-XX"
|
|
157
168
|
|
|
158
|
-
All three, uncertain, approximate, and unspecified attributes
|
|
159
|
-
into date calculations
|
|
169
|
+
All three, uncertain, approximate, and unspecified attributes
|
|
170
|
+
do not factor into date calculations
|
|
171
|
+
(like comparisons or successors etc.).
|
|
160
172
|
|
|
161
173
|
EDTF long or scientific years are mapped to normal date instances.
|
|
162
174
|
|
|
@@ -171,9 +183,10 @@ When printing date strings, EDTF-Ruby will try to avoid nested parentheses:
|
|
|
171
183
|
|
|
172
184
|
### Intervals
|
|
173
185
|
|
|
174
|
-
If you parse an EDTF interval,
|
|
175
|
-
|
|
176
|
-
|
|
186
|
+
If you parse an EDTF interval,
|
|
187
|
+
the EDTF-Ruby parser will return an instance of `EDTF::Interval`;
|
|
188
|
+
intervals mimic regular Ruby ranges,
|
|
189
|
+
but offer additional functionality.
|
|
177
190
|
|
|
178
191
|
> d = Date.edtf('1984-06?/2004-08?')
|
|
179
192
|
> d.from.uncertain?
|
|
@@ -181,14 +194,15 @@ functionality.
|
|
|
181
194
|
> d.include?(Date.new(1987,04,13))
|
|
182
195
|
=> false
|
|
183
196
|
|
|
184
|
-
The day is not included because interval has month precision.
|
|
197
|
+
The day is not included because interval has month precision.
|
|
198
|
+
However:
|
|
185
199
|
|
|
186
200
|
> d.cover?(Date.new(1987,04,13))
|
|
187
201
|
=> true
|
|
188
202
|
|
|
189
|
-
The day is still covered by the interval.
|
|
190
|
-
same way that Ruby optimizes numeric ranges.
|
|
191
|
-
plays into the way intervals are enumerated:
|
|
203
|
+
The day is still covered by the interval.
|
|
204
|
+
In general, optimized in the same way that Ruby optimizes numeric ranges.
|
|
205
|
+
Additionally, precision plays into the way intervals are enumerated:
|
|
192
206
|
|
|
193
207
|
> d.length
|
|
194
208
|
=> 243
|
|
@@ -198,14 +212,16 @@ There are 243 months between 1984-06-01 and 2004-08-31.
|
|
|
198
212
|
> d.step(36).map(&:year)
|
|
199
213
|
=> [1984, 1987, 1990, 1993, 1996, 1999, 2002]
|
|
200
214
|
|
|
201
|
-
Here we iterate through the interval in 36-month steps
|
|
202
|
-
the year.
|
|
215
|
+
Here we iterate through the interval in 36-month steps
|
|
216
|
+
and map each date to the year.
|
|
203
217
|
|
|
204
218
|
> Date.edtf('1582-10-01/1582-10-31').length
|
|
205
|
-
=>
|
|
219
|
+
=> 31
|
|
206
220
|
|
|
207
|
-
This interval has day precision,
|
|
208
|
-
|
|
221
|
+
This interval has day precision,
|
|
222
|
+
so 31 is the number of days in October 1582:
|
|
223
|
+
EDTF-Ruby uses the proleptic Gregorian calendar,
|
|
224
|
+
so the ten days skipped by the Gregorian calendar reform are included.
|
|
209
225
|
|
|
210
226
|
Intervals can be open or have unknown start or end dates.
|
|
211
227
|
|
|
@@ -216,8 +232,10 @@ Intervals can be open or have unknown start or end dates.
|
|
|
216
232
|
|
|
217
233
|
### Sets
|
|
218
234
|
|
|
219
|
-
EDTF supports two
|
|
220
|
-
|
|
235
|
+
EDTF supports two kinds of sets:
|
|
236
|
+
choice lists (meaning one date out of a list),
|
|
237
|
+
or inclusive lists.
|
|
238
|
+
In EDTF-Ruby, these are covered by the class `EDTF::Set`
|
|
221
239
|
and the `choice` attribute.
|
|
222
240
|
|
|
223
241
|
> s = Date.edtf('{1667,1668, 1670..1672}')
|
|
@@ -227,22 +245,23 @@ and the `choice` attribute.
|
|
|
227
245
|
> s.edtf
|
|
228
246
|
=> "[1667,1668,1670..1672]"
|
|
229
247
|
|
|
230
|
-
As you can see above,
|
|
231
|
-
|
|
248
|
+
As you can see above,
|
|
249
|
+
EDTF-Ruby remembers which parts of the set were specified as a range;
|
|
250
|
+
ranges are however enumerated for membership tests:
|
|
232
251
|
|
|
233
252
|
> s.include?(Date.edtf('1669'))
|
|
234
253
|
=> false
|
|
235
254
|
> s.include?(Date.edtf('1671'))
|
|
236
255
|
=> true
|
|
237
256
|
|
|
238
|
-
Even though we're still aware
|
|
239
|
-
element of the set:
|
|
257
|
+
Even though we're still aware
|
|
258
|
+
that the year 1671 is not directly an element of the set:
|
|
240
259
|
|
|
241
260
|
> s.length
|
|
242
261
|
=> 3
|
|
243
262
|
|
|
244
|
-
When in doubt, you can always map the set to an array.
|
|
245
|
-
enumerate all ranges:
|
|
263
|
+
When in doubt, you can always map the set to an array.
|
|
264
|
+
This will also enumerate all ranges:
|
|
246
265
|
|
|
247
266
|
> s.map(&:year)
|
|
248
267
|
=> [1667,1668,1670,1671,1672] # when enumerated there are 5 elements
|
|
@@ -258,14 +277,14 @@ EDTF sets also feature an `#earlier?` and `#later?` attribute:
|
|
|
258
277
|
|
|
259
278
|
### Decades and Centuries
|
|
260
279
|
|
|
261
|
-
The EDTF specification supports so called masked precision strings
|
|
262
|
-
decades or centuries.
|
|
263
|
-
|
|
280
|
+
The EDTF specification supports so called masked precision strings
|
|
281
|
+
to define decades or centuries.
|
|
282
|
+
EDTF-Ruby maps these to dedicated intervals
|
|
283
|
+
which always cover 10 or 100 years, respectively.
|
|
264
284
|
|
|
265
285
|
> d = Date.edtf!('196x')
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
=> EDTF::Decade
|
|
286
|
+
> d.edtf
|
|
287
|
+
=> "196x"
|
|
269
288
|
> d.class
|
|
270
289
|
=> EDTF::Decade
|
|
271
290
|
> d.min
|
|
@@ -277,13 +296,15 @@ always cover 10 or 100 years, respectively.
|
|
|
277
296
|
|
|
278
297
|
### Seasons
|
|
279
298
|
|
|
280
|
-
Finally, EDTF covers seasons.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
299
|
+
Finally, EDTF covers seasons.
|
|
300
|
+
Again, EDTF-Ruby provides a dedicated class for this.
|
|
301
|
+
Note that EDTF does not make any assumption about the specifics
|
|
302
|
+
(which months etc.) of the season
|
|
303
|
+
and you don't have to either;
|
|
304
|
+
however EDTF-Ruby defines method aliases
|
|
305
|
+
which allow you to access the seasons by the names
|
|
306
|
+
spring, summer, autumn (or fall), and winter, respectively.
|
|
307
|
+
You can also use the more neutral taxonomy of first, second, third, fourth.
|
|
287
308
|
|
|
288
309
|
> w = Date.edtf!('2003-24')
|
|
289
310
|
> w.winter?
|
|
@@ -299,24 +320,25 @@ fourth.
|
|
|
299
320
|
=> Mon, 31 May 2004
|
|
300
321
|
> s.to_a.length
|
|
301
322
|
=> 92
|
|
302
|
-
|
|
323
|
+
> w.to_a.length
|
|
303
324
|
=> 91
|
|
304
325
|
|
|
305
|
-
As you can see, spring 2004 lasted one day longer than winter 2003
|
|
306
|
-
that spring and winter here do not relate to the astronomical seasons
|
|
326
|
+
As you can see, spring 2004 lasted one day longer than winter 2003
|
|
327
|
+
(note that spring and winter here do not relate to the astronomical seasons
|
|
307
328
|
but strictly to three month periods).
|
|
308
329
|
|
|
309
|
-
Of course you can print seasons to EDTF strings, too.
|
|
310
|
-
be uncertain/approximate.
|
|
330
|
+
Of course you can print seasons to EDTF strings, too.
|
|
331
|
+
Finally, seasons can be uncertain/approximate.
|
|
311
332
|
|
|
312
333
|
> s.edtf
|
|
313
334
|
=> "2004-21"
|
|
314
335
|
> s.approximate!.edtf
|
|
315
|
-
=> "2004-21"
|
|
336
|
+
=> "2004-21~"
|
|
316
337
|
|
|
317
338
|
|
|
318
|
-
For additional features,
|
|
319
|
-
|
|
339
|
+
For additional features,
|
|
340
|
+
please take a look at the documentation
|
|
341
|
+
or the extensive list of rspec examples.
|
|
320
342
|
|
|
321
343
|
|
|
322
344
|
Contributing
|
|
@@ -326,16 +348,20 @@ You can check out a copy of the latest code using Git:
|
|
|
326
348
|
|
|
327
349
|
$ git clone https://github.com/inukshuk/edtf-ruby.git
|
|
328
350
|
|
|
329
|
-
To get started,
|
|
351
|
+
To get started, install the dependencies and run all tests:
|
|
330
352
|
|
|
331
353
|
$ cd edtf-ruby
|
|
332
354
|
$ bundle install
|
|
333
|
-
$ bundle exec
|
|
334
|
-
|
|
355
|
+
$ bundle exec rake
|
|
356
|
+
|
|
357
|
+
If you change the grammar in `lib/edtf/parser.y`,
|
|
358
|
+
regenerate the parser with `bundle exec rake racc`.
|
|
335
359
|
|
|
336
|
-
If you've found a bug or have a question,
|
|
337
|
-
|
|
338
|
-
|
|
360
|
+
If you've found a bug or have a question,
|
|
361
|
+
please open an issue on the
|
|
362
|
+
[EDTF-Ruby issue tracker](https://github.com/inukshuk/edtf-ruby/issues).
|
|
363
|
+
Or, for extra credit, clone the EDTF-Ruby repository,
|
|
364
|
+
write a failing example, fix the bug
|
|
339
365
|
and submit a pull request.
|
|
340
366
|
|
|
341
367
|
|
|
@@ -343,5 +369,5 @@ Credits
|
|
|
343
369
|
-------
|
|
344
370
|
EDTF-Ruby was written by Sylvester Keil and Ilja Srna.
|
|
345
371
|
|
|
346
|
-
Published under the terms and conditions of the FreeBSD License;
|
|
347
|
-
for details.
|
|
372
|
+
Published under the terms and conditions of the FreeBSD License;
|
|
373
|
+
see LICENSE for details.
|
data/lib/edtf/date.rb
CHANGED
|
@@ -19,7 +19,10 @@ class Date
|
|
|
19
19
|
extend Forwardable
|
|
20
20
|
|
|
21
21
|
class << self
|
|
22
|
-
|
|
22
|
+
def gregorian(year = -4712, month = 1, mday = 1)
|
|
23
|
+
new(year, month, mday, Date::GREGORIAN)
|
|
24
|
+
end
|
|
25
|
+
|
|
23
26
|
def edtf(input, options = {})
|
|
24
27
|
edtf!(input, options)
|
|
25
28
|
rescue
|
|
@@ -260,12 +263,34 @@ class Date
|
|
|
260
263
|
when ::Date
|
|
261
264
|
values <=> other.values
|
|
262
265
|
when EDTF::Interval, EDTF::Season, EDTF::Epoch
|
|
263
|
-
|
|
266
|
+
(c = other <=> self) && -c
|
|
264
267
|
else
|
|
265
268
|
nil
|
|
266
269
|
end
|
|
267
270
|
end
|
|
268
271
|
|
|
272
|
+
alias original_eql? eql?
|
|
273
|
+
alias original_hash hash
|
|
274
|
+
|
|
275
|
+
# Returns true if other is the same date and has the same EDTF attributes.
|
|
276
|
+
def eql?(other)
|
|
277
|
+
if original_eql?(other)
|
|
278
|
+
extended_hash == other.extended_hash && calendar == other.calendar
|
|
279
|
+
else
|
|
280
|
+
false
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Returns the original Date hash unless EDTF attributes are set.
|
|
285
|
+
def hash
|
|
286
|
+
h = extended_hash
|
|
287
|
+
if h.zero? && !calendar?
|
|
288
|
+
original_hash
|
|
289
|
+
else
|
|
290
|
+
[original_hash, h, @calendar].hash
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
269
294
|
|
|
270
295
|
# Returns an array of the current year, month, and day values filtered by
|
|
271
296
|
# the Date/Time's precision.
|
|
@@ -311,6 +336,18 @@ class Date
|
|
|
311
336
|
|
|
312
337
|
attr_writer :uncertain, :unspecified, :approximate
|
|
313
338
|
|
|
339
|
+
# Bits 0-1: precision (0 - day, 1 - month, 2 - year)
|
|
340
|
+
# Bits 2-4: uncertain year, month, day (Uncertainty#hash with base 1)
|
|
341
|
+
# Bits 5-7: approximate year, month, day (Uncertainty#hash with base 8)
|
|
342
|
+
# Bits 8-15: unspecified year, month, and day digits
|
|
343
|
+
def extended_hash
|
|
344
|
+
h = @precision == :year ? 2 : @precision == :month ? 1 : 0
|
|
345
|
+
h |= @uncertain.hash << 2 if @uncertain
|
|
346
|
+
h |= @approximate.hash << 2 if @approximate
|
|
347
|
+
h |= @unspecified.hash << 8 if @unspecified
|
|
348
|
+
h
|
|
349
|
+
end
|
|
350
|
+
|
|
314
351
|
def copy_extended_attributes(other)
|
|
315
352
|
@uncertain = other.uncertain.dup
|
|
316
353
|
@approximate = other.approximate.dup
|
data/lib/edtf/epoch.rb
CHANGED
|
@@ -44,7 +44,9 @@ module EDTF
|
|
|
44
44
|
case other
|
|
45
45
|
when Date
|
|
46
46
|
cover?(other) ? 0 : to_date <=> other
|
|
47
|
-
when Interval
|
|
47
|
+
when Interval
|
|
48
|
+
(c = other <=> self) && -c
|
|
49
|
+
when Season
|
|
48
50
|
[min, max] <=> [other.min, other.max]
|
|
49
51
|
when Epoch
|
|
50
52
|
[year, self.class.duration] <=> [other.year, other.class.duration]
|
data/lib/edtf/interval.rb
CHANGED
|
@@ -166,18 +166,8 @@ module EDTF
|
|
|
166
166
|
|
|
167
167
|
other = other.day_precision
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
max.day_precision! == other
|
|
172
|
-
when unknown_end?
|
|
173
|
-
min.day_precision! == other
|
|
174
|
-
when open_start?
|
|
175
|
-
max.day_precision! >= other
|
|
176
|
-
when open_end?
|
|
177
|
-
min.day_precision! <= other
|
|
178
|
-
else
|
|
179
|
-
min.day_precision! <= other && other <= max.day_precision!
|
|
180
|
-
end
|
|
169
|
+
(unbounded_start? || min.day_precision! <= other) &&
|
|
170
|
+
(unbounded_end? || other <= max.day_precision!)
|
|
181
171
|
end
|
|
182
172
|
|
|
183
173
|
# call-seq:
|
|
@@ -268,12 +258,20 @@ module EDTF
|
|
|
268
258
|
max
|
|
269
259
|
end
|
|
270
260
|
|
|
261
|
+
# Intervals are compared by their min and max dates. Open and unknown
|
|
262
|
+
# starts and ends are treated like -/+ infinity, with open being the
|
|
263
|
+
# more extreme of the two. Dates are equal to an interval if they are
|
|
264
|
+
# covered by it.
|
|
271
265
|
def <=>(other)
|
|
272
266
|
case other
|
|
273
267
|
when Interval, Season, Epoch
|
|
274
|
-
|
|
268
|
+
bounds <=> bounds_of(other)
|
|
275
269
|
when Date
|
|
276
|
-
|
|
270
|
+
case
|
|
271
|
+
when cover?(other) then 0
|
|
272
|
+
when unbounded_start? then -1
|
|
273
|
+
else min.day_precision <=> other.day_precision
|
|
274
|
+
end
|
|
277
275
|
else
|
|
278
276
|
nil
|
|
279
277
|
end
|
|
@@ -282,7 +280,8 @@ module EDTF
|
|
|
282
280
|
def ===(other)
|
|
283
281
|
case other
|
|
284
282
|
when Interval
|
|
285
|
-
|
|
283
|
+
(other.unbounded_start? ? unbounded_start? : cover?(other.min)) &&
|
|
284
|
+
(other.unbounded_end? ? unbounded_end? : cover?(other.max))
|
|
286
285
|
when Date
|
|
287
286
|
cover?(other)
|
|
288
287
|
else
|
|
@@ -301,6 +300,32 @@ module EDTF
|
|
|
301
300
|
|
|
302
301
|
alias to_s edtf
|
|
303
302
|
|
|
303
|
+
protected
|
|
304
|
+
|
|
305
|
+
def unbounded_start?
|
|
306
|
+
open_start? || unknown_start?
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def unbounded_end?
|
|
310
|
+
open_end? || unknown_end?
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
START_RANK = { :open => -2, :unknown => -1 }.freeze
|
|
314
|
+
END_RANK = { :unknown => 1, :open => 2 }.freeze
|
|
315
|
+
|
|
316
|
+
def bounds
|
|
317
|
+
[
|
|
318
|
+
unbounded_start? ? START_RANK[from] : 0, min,
|
|
319
|
+
unbounded_end? ? END_RANK[to] : 0, max
|
|
320
|
+
]
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
private
|
|
324
|
+
|
|
325
|
+
def bounds_of(other)
|
|
326
|
+
other.is_a?(Interval) ? other.bounds : [0, other.min, 0, other.max]
|
|
327
|
+
end
|
|
328
|
+
|
|
304
329
|
end
|
|
305
330
|
|
|
306
331
|
end
|