fat_core 5.1.0 → 5.3.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/.rubocop.yml +5 -21
- data/Gemfile +14 -8
- data/README.org +170 -19
- data/Rakefile +10 -3
- data/bin/easters +22 -12
- data/fat_core.gemspec +2 -12
- data/lib/fat_core/date.rb +247 -258
- data/lib/fat_core/enumerable.rb +1 -1
- data/lib/fat_core/nil.rb +1 -1
- data/lib/fat_core/numeric.rb +19 -14
- data/lib/fat_core/range.rb +5 -5
- data/lib/fat_core/string.rb +37 -17
- data/lib/fat_core/symbol.rb +1 -1
- data/lib/fat_core/version.rb +1 -1
- data/spec/lib/date_spec.rb +172 -13
- data/spec/lib/enumerable_spec.rb +7 -4
- data/spec/lib/kernel_spec.rb +6 -6
- data/spec/lib/range_spec.rb +16 -14
- data/spec/lib/string_spec.rb +6 -11
- data/spec/spec_helper.rb +4 -0
- metadata +5 -131
- /data/spec/lib/{bigdecimal_spec.rb → big_decimal_spec.rb} +0 -0
- /data/spec/lib/{nil_spec.rb → nil_class_spec.rb} +0 -0
data/lib/fat_core/enumerable.rb
CHANGED
data/lib/fat_core/nil.rb
CHANGED
data/lib/fat_core/numeric.rb
CHANGED
@@ -15,13 +15,11 @@ module FatCore
|
|
15
15
|
#
|
16
16
|
# @return [Integer] -1, 0, or 1 for negative, zero or positive self
|
17
17
|
def signum
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
0
|
24
|
-
end
|
18
|
+
raise NotImplementedError unless real?
|
19
|
+
return 1 if positive?
|
20
|
+
return -1 if negative?
|
21
|
+
|
22
|
+
0
|
25
23
|
end
|
26
24
|
|
27
25
|
# Convert this number into a string and insert grouping commas into the
|
@@ -65,7 +63,7 @@ module FatCore
|
|
65
63
|
|
66
64
|
# Only convert to string numbers with exponent unless they are
|
67
65
|
# less than 1 (to ensure that really small numbers round to 0.0)
|
68
|
-
return to_s if abs > 1.0 && to_s
|
66
|
+
return to_s if abs > 1.0 && to_s.include?('e')
|
69
67
|
|
70
68
|
# Round if places given
|
71
69
|
str =
|
@@ -135,13 +133,20 @@ module FatCore
|
|
135
133
|
mins, secs = divmod(60)
|
136
134
|
hrs, mins = mins.divmod(60)
|
137
135
|
if frac.round(5) > 0.0
|
138
|
-
format(
|
139
|
-
|
140
|
-
|
141
|
-
|
136
|
+
format(
|
137
|
+
'%02<hrs>d:%02<mins>d:%02<secs>d.%<frac>d',
|
138
|
+
{
|
139
|
+
hrs: hrs,
|
140
|
+
mins: mins,
|
141
|
+
secs: secs,
|
142
|
+
frac: frac.round(5) * 100
|
143
|
+
},
|
144
|
+
)
|
142
145
|
else
|
143
|
-
format(
|
144
|
-
|
146
|
+
format(
|
147
|
+
'%02<hrs>d:%02<mins>d:%02<secs>d',
|
148
|
+
{ hrs: hrs, mins: mins, secs: secs },
|
149
|
+
)
|
145
150
|
end
|
146
151
|
end
|
147
152
|
|
data/lib/fat_core/range.rb
CHANGED
@@ -128,11 +128,11 @@ module FatCore
|
|
128
128
|
# @param other [Range] the Range self is intersected with
|
129
129
|
# @return [Range, nil] a Range representing the intersection
|
130
130
|
def intersection(other)
|
131
|
-
return
|
131
|
+
return unless overlaps?(other)
|
132
132
|
|
133
133
|
([min, other.min].max..[max, other.max].min)
|
134
134
|
end
|
135
|
-
|
135
|
+
alias_method :&, :intersection
|
136
136
|
|
137
137
|
# Return a Range that represents the union between this range and the
|
138
138
|
# `other` range. If there is no overlap and self is not contiguous with
|
@@ -146,11 +146,11 @@ module FatCore
|
|
146
146
|
# @param other [Range] the Range self is union-ed with
|
147
147
|
# @return [Range, nil] a Range representing the union
|
148
148
|
def union(other)
|
149
|
-
return
|
149
|
+
return unless overlaps?(other) || contiguous?(other)
|
150
150
|
|
151
151
|
([min, other.min].min..[max, other.max].max)
|
152
152
|
end
|
153
|
-
|
153
|
+
alias_method :+, :union
|
154
154
|
|
155
155
|
# The difference method, -, removes the overlapping part of the other
|
156
156
|
# argument from self. Because in the case where self is a superset of the
|
@@ -187,7 +187,7 @@ module FatCore
|
|
187
187
|
[(min..isec.min.pred), (isec.max.succ..max)]
|
188
188
|
end
|
189
189
|
end
|
190
|
-
|
190
|
+
alias_method :-, :difference
|
191
191
|
|
192
192
|
# Allow erb or erubis documents to directly interpolate a Range.
|
193
193
|
#
|
data/lib/fat_core/string.rb
CHANGED
@@ -63,7 +63,7 @@ module FatCore
|
|
63
63
|
result << w
|
64
64
|
first_word_on_line = false
|
65
65
|
line_width_so_far += 1 + w.length
|
66
|
-
next
|
66
|
+
next if line_width_so_far < width
|
67
67
|
|
68
68
|
result << "\n"
|
69
69
|
line_width_so_far = 0
|
@@ -108,9 +108,11 @@ module FatCore
|
|
108
108
|
# @return [Date] the translated Date
|
109
109
|
def as_date
|
110
110
|
if self =~ %r{(?<yr>\d\d\d\d)[-/]?(?<mo>\d\d?)[-/]?(?<dy>\d\d?)}
|
111
|
-
::Date.new(
|
112
|
-
|
113
|
-
|
111
|
+
::Date.new(
|
112
|
+
Regexp.last_match[:yr].to_i,
|
113
|
+
Regexp.last_match[:mo].to_i,
|
114
|
+
Regexp.last_match[:dy].to_i,
|
115
|
+
)
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
@@ -149,8 +151,26 @@ module FatCore
|
|
149
151
|
#
|
150
152
|
# @return [String]
|
151
153
|
def entitle
|
152
|
-
little_words = %w[
|
153
|
-
|
154
|
+
little_words = %w[
|
155
|
+
a
|
156
|
+
an
|
157
|
+
the
|
158
|
+
at
|
159
|
+
for
|
160
|
+
up
|
161
|
+
and
|
162
|
+
but
|
163
|
+
or
|
164
|
+
nor
|
165
|
+
in
|
166
|
+
on
|
167
|
+
under
|
168
|
+
of
|
169
|
+
from
|
170
|
+
as
|
171
|
+
by
|
172
|
+
to
|
173
|
+
]
|
154
174
|
preserve_acronyms = !all_upper?
|
155
175
|
newwords = []
|
156
176
|
capitalize_next = false
|
@@ -159,26 +179,26 @@ module FatCore
|
|
159
179
|
words.each_with_index do |w, k|
|
160
180
|
first = k.zero?
|
161
181
|
last = (k == last_k)
|
162
|
-
if
|
182
|
+
if %r{c/o}i.match?(w)
|
163
183
|
# Care of
|
164
184
|
newwords.push('c/o')
|
165
|
-
elsif
|
185
|
+
elsif /^p\.?o\.?$/i.match?(w)
|
166
186
|
# Post office
|
167
187
|
newwords.push('P.O.')
|
168
|
-
elsif
|
188
|
+
elsif /^[0-9]+(st|nd|rd|th)$/i.match?(w)
|
169
189
|
# Ordinals
|
170
190
|
newwords.push(w.downcase)
|
171
|
-
elsif
|
191
|
+
elsif /^(cr|dr|st|rd|ave|pk|cir)$/i.match?(w)
|
172
192
|
# Common abbrs to capitalize
|
173
193
|
newwords.push(w.capitalize)
|
174
|
-
elsif
|
194
|
+
elsif /^(us|ne|se|rr)$/i.match?(w)
|
175
195
|
# Common 2-letter abbrs to upcase
|
176
196
|
newwords.push(w.upcase)
|
177
|
-
elsif
|
197
|
+
elsif /^[0-9].*$/i.match?(w)
|
178
198
|
# Other runs starting with numbers,
|
179
199
|
# like 3-A
|
180
200
|
newwords.push(w.upcase)
|
181
|
-
elsif
|
201
|
+
elsif /^(N|S|E|W|NE|NW|SE|SW)$/i.match?(w)
|
182
202
|
# Compass directions all caps
|
183
203
|
newwords.push(w.upcase)
|
184
204
|
elsif w =~ /^[^aeiouy]*$/i && w.size > 2
|
@@ -202,7 +222,7 @@ module FatCore
|
|
202
222
|
newwords.push(w.capitalize)
|
203
223
|
end
|
204
224
|
# Capitalize following a ':'
|
205
|
-
capitalize_next = true if
|
225
|
+
capitalize_next = true if /:\s*\z/.match?(newwords.last)
|
206
226
|
end
|
207
227
|
newwords.join(' ')
|
208
228
|
end
|
@@ -272,11 +292,11 @@ module FatCore
|
|
272
292
|
matcher = matcher.strip.gsub(/[\*.,']/, '')
|
273
293
|
if matcher.start_with?(':')
|
274
294
|
begin_anchor = true
|
275
|
-
matcher.
|
295
|
+
matcher.delete_prefix!(':')
|
276
296
|
end
|
277
297
|
if matcher.end_with?(':')
|
278
298
|
end_anchor = true
|
279
|
-
matcher.
|
299
|
+
matcher.delete_suffix!(':')
|
280
300
|
end
|
281
301
|
target = gsub(/[\*.,']/, '')
|
282
302
|
matchers = matcher.split(/[: ]+/)
|
@@ -364,7 +384,7 @@ module FatCore
|
|
364
384
|
# @return [String] commified number as a String
|
365
385
|
def commas(places = nil)
|
366
386
|
numeric_re = /\A([-+])?([\d_]*)((\.)?([\d_]*))?([eE][+-]?[\d_]+)?\z/
|
367
|
-
return self unless clean
|
387
|
+
return self unless clean&.match?(numeric_re)
|
368
388
|
|
369
389
|
to_f.commas(places)
|
370
390
|
end
|
data/lib/fat_core/symbol.rb
CHANGED
@@ -16,7 +16,7 @@ module FatCore
|
|
16
16
|
def as_string
|
17
17
|
to_s.tr('_', ' ').split.join(' ').entitle
|
18
18
|
end
|
19
|
-
|
19
|
+
alias_method :entitle, :as_string
|
20
20
|
|
21
21
|
# Return self. This (together with String#as_sym) allows `#as_sym` to be
|
22
22
|
# applied to a string or Symbol and get back a Symbol with out testing for
|
data/lib/fat_core/version.rb
CHANGED
data/spec/lib/date_spec.rb
CHANGED
@@ -23,21 +23,21 @@ describe Date do
|
|
23
23
|
expect(described_class.ensure(described_class.today).class).to be described_class
|
24
24
|
end
|
25
25
|
|
26
|
-
it 'converts Time as a
|
27
|
-
expect(described_class.ensure_date(Time.now).class).to be
|
28
|
-
expect(described_class.ensure(Time.now).class).to be
|
26
|
+
it 'converts Time as a DateTime' do
|
27
|
+
expect(described_class.ensure_date(Time.now).class).to be DateTime
|
28
|
+
expect(described_class.ensure(Time.now).class).to be DateTime
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'raises an error for bad date string' do
|
32
|
-
expect { described_class.ensure_date('2012-mm-tu') }.to raise_error(/
|
33
|
-
expect { described_class.ensure('2012-mm-tu') }.to raise_error(/
|
32
|
+
expect { described_class.ensure_date('2012-mm-tu') }.to raise_error(/cannot convert string/)
|
33
|
+
expect { described_class.ensure('2012-mm-tu') }.to raise_error(/cannot convert string/)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'raises an error for unknown class' do
|
37
37
|
expect { described_class.ensure_date([2011, 11, 12]) }
|
38
|
-
.to raise_error(/
|
38
|
+
.to raise_error(/cannot convert/)
|
39
39
|
expect { described_class.ensure([2011, 11, 12]) }
|
40
|
-
.to raise_error(/
|
40
|
+
.to raise_error(/cannot convert/)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -61,6 +61,32 @@ describe Date do
|
|
61
61
|
expect { described_class.days_in_month(2004, 13) }.to raise_error(ArgumentError)
|
62
62
|
end
|
63
63
|
|
64
|
+
it 'knows a Date\'s half year' do
|
65
|
+
expect(Date.parse('2024-05-14').half).to eq(1)
|
66
|
+
expect(Date.parse('2024-09-14').half).to eq(2)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'knows a Date\'s quarter year' do
|
70
|
+
expect(Date.parse('2024-03-14').quarter).to eq(1)
|
71
|
+
expect(Date.parse('2024-05-14').quarter).to eq(2)
|
72
|
+
expect(Date.parse('2024-09-14').quarter).to eq(3)
|
73
|
+
expect(Date.parse('2024-11-14').quarter).to eq(4)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'knows a Date\'s bimonth' do
|
77
|
+
expect(Date.parse('2024-03-14').bimonth).to eq(2)
|
78
|
+
expect(Date.parse('2024-05-14').bimonth).to eq(3)
|
79
|
+
expect(Date.parse('2024-09-14').bimonth).to eq(5)
|
80
|
+
expect(Date.parse('2024-11-14').bimonth).to eq(6)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'knows a Date\'s semimonth' do
|
84
|
+
expect(Date.parse('2024-03-14').semimonth).to eq(5)
|
85
|
+
expect(Date.parse('2024-05-14').semimonth).to eq(9)
|
86
|
+
expect(Date.parse('2024-09-24').semimonth).to eq(18)
|
87
|
+
expect(Date.parse('2024-11-14').semimonth).to eq(21)
|
88
|
+
end
|
89
|
+
|
64
90
|
it 'knows the nth weekday in a year, month' do
|
65
91
|
# Sunday is 0, Saturday is 6
|
66
92
|
# January 2014
|
@@ -246,6 +272,14 @@ describe Date do
|
|
246
272
|
expect(described_class.parse_spec('2011/08/05')).to eq described_class.parse('2011-08-05')
|
247
273
|
end
|
248
274
|
|
275
|
+
it 'parses YYYY-ddd day-of-year dates correctly' do
|
276
|
+
expect(described_class.parse_spec('2011-115')).to eq described_class.parse('2011-04-25')
|
277
|
+
expect(described_class.parse_spec('2011/001')).to eq described_class.parse('2011-01-01')
|
278
|
+
expect {
|
279
|
+
described_class.parse_spec('2023-366')
|
280
|
+
}.to raise_error(/invalid day-of-year/)
|
281
|
+
end
|
282
|
+
|
249
283
|
it "parses week numbers such as 'W23' or '23W' correctly" do
|
250
284
|
expect(described_class.parse_spec('W1')).to eq described_class.parse('2012-01-02')
|
251
285
|
expect(described_class.parse_spec('W23')).to eq described_class.parse('2012-06-04')
|
@@ -257,7 +291,19 @@ describe Date do
|
|
257
291
|
}.to raise_error(ArgumentError)
|
258
292
|
end
|
259
293
|
|
260
|
-
it
|
294
|
+
it "parses week-day numbers such as 'W23-4' or '23W-3' correctly" do
|
295
|
+
expect(described_class.parse_spec('W1-4')).to eq described_class.parse('2012-01-05')
|
296
|
+
expect(described_class.parse_spec('W23-3')).to eq described_class.parse('2012-06-06')
|
297
|
+
expect(described_class.parse_spec('W23-3', :to)).to eq described_class.parse('2012-06-06')
|
298
|
+
expect(described_class.parse_spec('23W-2')).to eq described_class.parse('2012-06-05')
|
299
|
+
expect(described_class.parse_spec('23W-2', :to)).to eq described_class.parse('2012-06-05')
|
300
|
+
expect {
|
301
|
+
described_class.parse_spec('W38-9', :to)
|
302
|
+
}.to raise_error(ArgumentError)
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'parse year-week numbers \'YYYY-Wnn\' correctly' do
|
306
|
+
expect(described_class.parse_spec('2002-W52')).to eq described_class.parse('2002-12-23')
|
261
307
|
expect(described_class.parse_spec('2003-W1')).to eq described_class.parse('2002-12-30')
|
262
308
|
expect(described_class.parse_spec('2003-W1', :to)).to eq described_class.parse('2003-01-05')
|
263
309
|
expect(described_class.parse_spec('2003-W23')).to eq described_class.parse('2003-06-02')
|
@@ -269,6 +315,27 @@ describe Date do
|
|
269
315
|
}.to raise_error(ArgumentError)
|
270
316
|
end
|
271
317
|
|
318
|
+
it 'parse year-week-day numbers \'YYYY-Wnn-d\' correctly' do
|
319
|
+
# Examples from the Wikipedia page on ISO 8601 dates
|
320
|
+
expect(described_class.parse_spec('1976-W53-6')).to eq described_class.parse('1977-01-01')
|
321
|
+
expect(described_class.parse_spec('1977-W52-6')).to eq described_class.parse('1977-12-31')
|
322
|
+
expect(described_class.parse_spec('1977-W52-7')).to eq described_class.parse('1978-01-01')
|
323
|
+
expect(described_class.parse_spec('1978-W01-1')).to eq described_class.parse('1978-01-02')
|
324
|
+
expect(described_class.parse_spec('1978-W52-7')).to eq described_class.parse('1978-12-31')
|
325
|
+
expect(described_class.parse_spec('1979-W01-1')).to eq described_class.parse('1979-01-01')
|
326
|
+
expect(described_class.parse_spec('1979-W52-7')).to eq described_class.parse('1979-12-30')
|
327
|
+
expect(described_class.parse_spec('1980-W01-1')).to eq described_class.parse('1979-12-31')
|
328
|
+
expect(described_class.parse_spec('1980-W52-7')).to eq described_class.parse('1980-12-28')
|
329
|
+
expect(described_class.parse_spec('1981-W01-2')).to eq described_class.parse('1980-12-30')
|
330
|
+
expect(described_class.parse_spec('1981-W01-3')).to eq described_class.parse('1980-12-31')
|
331
|
+
expect(described_class.parse_spec('1981-W01-4')).to eq described_class.parse('1981-01-01')
|
332
|
+
expect(described_class.parse_spec('1981-W53-4')).to eq described_class.parse('1981-12-31')
|
333
|
+
expect(described_class.parse_spec('1981-W53-5')).to eq described_class.parse('1982-01-01')
|
334
|
+
expect {
|
335
|
+
described_class.parse_spec('2003-W83', :to)
|
336
|
+
}.to raise_error(ArgumentError)
|
337
|
+
end
|
338
|
+
|
272
339
|
it 'parses year-half specs such as YYYY-NH or YYYY-HN' do
|
273
340
|
expect(described_class.parse_spec('2011-2H', :from)).to eq described_class.parse('2011-07-01')
|
274
341
|
expect(described_class.parse_spec('2011-2H', :to)).to eq described_class.parse('2011-12-31')
|
@@ -311,7 +378,8 @@ describe Date do
|
|
311
378
|
expect(described_class.parse_spec('10', :from)).to eq described_class.parse('2012-10-01')
|
312
379
|
expect(described_class.parse_spec('10', :to)).to eq described_class.parse('2012-10-31')
|
313
380
|
expect { described_class.parse_spec('99') }.to raise_error(ArgumentError)
|
314
|
-
|
381
|
+
# This is a valid day-of-year spec
|
382
|
+
expect { described_class.parse_spec('011') }.not_to raise_error(ArgumentError)
|
315
383
|
end
|
316
384
|
|
317
385
|
it 'parses month-day specs such as MM-DD' do
|
@@ -335,11 +403,102 @@ describe Date do
|
|
335
403
|
expect { described_class.parse_spec('99999') }.to raise_error(ArgumentError)
|
336
404
|
end
|
337
405
|
|
406
|
+
it 'parses half-month specs such as YYYY-MM-I and YYYY-MM-II' do
|
407
|
+
expect(described_class.parse_spec('2010-09-I', :from)).to eq described_class.parse('2010-09-01')
|
408
|
+
expect(described_class.parse_spec('2010-09-I', :to)).to eq described_class.parse('2010-09-15')
|
409
|
+
expect(described_class.parse_spec('2010-09-II', :from)).to eq described_class.parse('2010-09-16')
|
410
|
+
expect(described_class.parse_spec('2010-09-II', :to)).to eq described_class.parse('2010-09-30')
|
411
|
+
end
|
412
|
+
|
413
|
+
it 'parses intra-month week specs such as YYYY-MM-i and YYYY-MM-v begin Sunday' do
|
414
|
+
expect(described_class.parse_spec('2010-09-i', :from)).to eq described_class.parse('2010-09-01')
|
415
|
+
expect(described_class.parse_spec('2010-09-ii', :from)).to eq described_class.parse('2010-09-06')
|
416
|
+
expect(described_class.parse_spec('2010-09-iii', :from)).to eq described_class.parse('2010-09-13')
|
417
|
+
expect(described_class.parse_spec('2010-09-iv', :from)).to eq described_class.parse('2010-09-20')
|
418
|
+
expect(described_class.parse_spec('2010-09-v', :from)).to eq described_class.parse('2010-09-27')
|
419
|
+
expect { described_class.parse_spec('2010-09-vi', :from) }.to raise_error(/no week/)
|
420
|
+
expect(described_class.parse_spec('2011-01-vi', :from)).to eq described_class.parse('2011-01-31')
|
421
|
+
|
422
|
+
expect(described_class.parse_spec('2010-09-i', :to)).to eq described_class.parse('2010-09-05')
|
423
|
+
expect(described_class.parse_spec('2010-09-ii', :to)).to eq described_class.parse('2010-09-12')
|
424
|
+
expect(described_class.parse_spec('2010-09-iii', :to)).to eq described_class.parse('2010-09-19')
|
425
|
+
expect(described_class.parse_spec('2010-09-iv', :to)).to eq described_class.parse('2010-09-26')
|
426
|
+
expect(described_class.parse_spec('2010-09-v', :to)).to eq described_class.parse('2010-09-30')
|
427
|
+
expect { described_class.parse_spec('2010-09-vi', :to) }.to raise_error(/no week/)
|
428
|
+
expect(described_class.parse_spec('2011-01-vi', :to)).to eq described_class.parse('2011-01-31')
|
429
|
+
end
|
430
|
+
|
431
|
+
it 'parses intra-month week specs such as YYYY-MM-i and YYYY-MM-v begin Monday' do
|
432
|
+
expect(described_class.parse_spec('2010-09-i', :from)).to eq described_class.parse('2010-09-01')
|
433
|
+
expect(described_class.parse_spec('2010-09-ii', :from)).to eq described_class.parse('2010-09-06')
|
434
|
+
expect(described_class.parse_spec('2010-09-iii', :from)).to eq described_class.parse('2010-09-13')
|
435
|
+
expect(described_class.parse_spec('2010-09-iv', :from)).to eq described_class.parse('2010-09-20')
|
436
|
+
expect(described_class.parse_spec('2010-09-v', :from)).to eq described_class.parse('2010-09-27')
|
437
|
+
expect { described_class.parse_spec('2010-09-vi', :from) }.to raise_error(/no week/)
|
438
|
+
expect { described_class.parse_spec('2010-10-vi', :from) }.to raise_error(/no week/)
|
439
|
+
expect(described_class.parse_spec('2011-01-vi', :to)).to eq described_class.parse('2011-01-31')
|
440
|
+
|
441
|
+
expect(described_class.parse_spec('2010-09-i', :to)).to eq described_class.parse('2010-09-05')
|
442
|
+
expect(described_class.parse_spec('2010-09-ii', :to)).to eq described_class.parse('2010-09-12')
|
443
|
+
expect(described_class.parse_spec('2010-09-iii', :to)).to eq described_class.parse('2010-09-19')
|
444
|
+
expect(described_class.parse_spec('2010-09-iv', :to)).to eq described_class.parse('2010-09-26')
|
445
|
+
expect(described_class.parse_spec('2010-09-v', :to)).to eq described_class.parse('2010-09-30')
|
446
|
+
expect { described_class.parse_spec('2010-09-vi', :to) }.to raise_error(/no week/)
|
447
|
+
expect { described_class.parse_spec('2010-09-vi', :to) }.to raise_error(/no week/)
|
448
|
+
expect(described_class.parse_spec('2011-01-vi', :to)).to eq described_class.parse('2011-01-31')
|
449
|
+
|
450
|
+
travel_to Time.local(2020, 9, 15)
|
451
|
+
expect(described_class.parse_spec('9-i', :from)).to eq described_class.parse('2020-09-01')
|
452
|
+
expect(described_class.parse_spec('09-i', :to)).to eq described_class.parse('2020-09-06')
|
453
|
+
expect(described_class.parse_spec('09-iii', :from)).to eq described_class.parse('2020-09-14')
|
454
|
+
expect(described_class.parse_spec('09-iii', :to)).to eq described_class.parse('2020-09-20')
|
455
|
+
expect(described_class.parse_spec('09-v', :from)).to eq described_class.parse('2020-09-28')
|
456
|
+
expect(described_class.parse_spec('09-v', :to)).to eq described_class.parse('2020-09-30')
|
457
|
+
|
458
|
+
expect(described_class.parse_spec('i', :to)).to eq described_class.parse('2020-09-06')
|
459
|
+
expect(described_class.parse_spec('ii', :to)).to eq described_class.parse('2020-09-13')
|
460
|
+
expect(described_class.parse_spec('iii', :to)).to eq described_class.parse('2020-09-20')
|
461
|
+
expect(described_class.parse_spec('iv', :to)).to eq described_class.parse('2020-09-27')
|
462
|
+
expect(described_class.parse_spec('v', :to)).to eq described_class.parse('2020-09-30')
|
463
|
+
travel_back
|
464
|
+
end
|
465
|
+
|
466
|
+
it 'parses Easter-relative dates' do
|
467
|
+
expect(described_class.parse_spec('2024-E')).to eq described_class.parse('2024-03-31')
|
468
|
+
expect(described_class.parse_spec('2024-E+12')).to eq described_class.parse('2024-04-12')
|
469
|
+
expect(described_class.parse_spec('2024-E-12')).to eq described_class.parse('2024-03-19')
|
470
|
+
travel_to Time.local(2020, 9, 15)
|
471
|
+
expect(described_class.parse_spec('E-12')).to eq described_class.parse('2020-03-31')
|
472
|
+
expect(described_class.parse_spec('E+12')).to eq described_class.parse('2020-04-24')
|
473
|
+
travel_back
|
474
|
+
end
|
475
|
+
|
476
|
+
it 'parses DOW ordinals' do
|
477
|
+
expect(described_class.parse_spec('2024-11-4Th')).to eq described_class.parse('2024-11-28')
|
478
|
+
expect { described_class.parse_spec('2024-11-40Th') }.to raise_error(/invalid ordinal/)
|
479
|
+
expect { described_class.parse_spec('2024-15-4Th') }.to raise_error(/invalid month/)
|
480
|
+
expect { described_class.parse_spec('2024-11-5Th') }.to raise_error(/there is no 5th/i)
|
481
|
+
travel_to Time.local(2020, 9, 15)
|
482
|
+
expect(described_class.parse_spec('11-4Th')).to eq described_class.parse('2020-11-26')
|
483
|
+
expect(described_class.parse_spec('4Th')).to eq described_class.parse('2020-09-24')
|
484
|
+
travel_back
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'parses DOY three-digit specs' do
|
488
|
+
expect(described_class.parse_spec('2024-001')).to eq described_class.parse('2024-01-01')
|
489
|
+
expect(described_class.parse_spec('2024-366')).to eq described_class.parse('2024-12-31')
|
490
|
+
expect { described_class.parse_spec('2024-885') }.to raise_error(/invalid day-of-year/)
|
491
|
+
travel_to Time.local(2020, 9, 15)
|
492
|
+
expect(described_class.parse_spec('150')).to eq described_class.parse('2020-05-29')
|
493
|
+
travel_back
|
494
|
+
end
|
495
|
+
|
338
496
|
it 'parses relative day names: today, yesterday' do
|
339
497
|
expect(described_class.parse_spec('today')).to eq described_class.current
|
340
498
|
expect(described_class.parse_spec('this_day')).to eq described_class.current
|
341
499
|
expect(described_class.parse_spec('yesterday')).to eq described_class.current - 1.day
|
342
500
|
expect(described_class.parse_spec('last_day')).to eq described_class.current - 1.day
|
501
|
+
expect(described_class.parse_spec('tomorrow')).to eq described_class.current + 1.day
|
343
502
|
end
|
344
503
|
|
345
504
|
it 'parses relative weeks: this_week, last_week' do
|
@@ -445,7 +604,7 @@ describe Date do
|
|
445
604
|
expect(described_class.mo_name_to_num("octagon")).to eq 10
|
446
605
|
expect(described_class.mo_name_to_num(" novena this month")).to eq 11
|
447
606
|
expect(described_class.mo_name_to_num("decimal")).to eq 12
|
448
|
-
expect(described_class.mo_name_to_num(" dewey decimal")).to
|
607
|
+
expect(described_class.mo_name_to_num(" dewey decimal")).to be_nil
|
449
608
|
end
|
450
609
|
end
|
451
610
|
end
|
@@ -704,7 +863,6 @@ describe Date do
|
|
704
863
|
.to be false
|
705
864
|
expect(described_class.parse('2013-11-04').beginning_of_chunk?(:week))
|
706
865
|
.to be true
|
707
|
-
# Sunday is not beginning of commercial week
|
708
866
|
expect(described_class.parse('2013-11-03').beginning_of_chunk?(:week))
|
709
867
|
.to be false
|
710
868
|
expect(described_class.parse('2013-11-01').beginning_of_chunk?(:day))
|
@@ -758,8 +916,9 @@ describe Date do
|
|
758
916
|
.to be false
|
759
917
|
expect(described_class.parse('2013-11-04').end_of_chunk?(:week))
|
760
918
|
.to be false
|
761
|
-
|
762
|
-
|
919
|
+
expect(described_class.parse('2013-11-09').end_of_chunk?(:week))
|
920
|
+
.to be false
|
921
|
+
expect(described_class.parse('2013-11-10').end_of_chunk?(:week))
|
763
922
|
.to be true
|
764
923
|
expect(described_class.parse('2013-11-01').end_of_chunk?(:day))
|
765
924
|
.to be true
|
data/spec/lib/enumerable_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'fat_core/enumerable'
|
|
4
4
|
describe Enumerable do
|
5
5
|
it 'enumerates groups of size k' do
|
6
6
|
letters = ('a'..'z').to_a
|
7
|
-
letters.groups_of(3).each do |
|
7
|
+
letters.groups_of(3).each do |_k, grp|
|
8
8
|
expect(grp.class).to eq Array
|
9
9
|
if grp.last == 'z'
|
10
10
|
expect(grp.size).to eq(2)
|
@@ -34,14 +34,17 @@ describe Enumerable do
|
|
34
34
|
|
35
35
|
it 'returns nil enumerating a beginless Range' do
|
36
36
|
bless = (..100)
|
37
|
-
result = bless.each_with_flags { |
|
38
|
-
expect(result).to
|
37
|
+
result = bless.each_with_flags { |_l, _first, _last| 44 }
|
38
|
+
expect(result).to be_nil
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'enumerates an endless Range' do
|
42
42
|
eless = (1..)
|
43
43
|
num = 0
|
44
|
-
eless.each_with_flags
|
44
|
+
eless.each_with_flags do |i, _first, _last|
|
45
|
+
num += i
|
46
|
+
break if i >= 100
|
47
|
+
end
|
45
48
|
# Look at me, I'm Gauss
|
46
49
|
expect(num).to eq(5050)
|
47
50
|
end
|
data/spec/lib/kernel_spec.rb
CHANGED
@@ -3,11 +3,11 @@ require 'fat_core/kernel'
|
|
3
3
|
|
4
4
|
describe Kernel do
|
5
5
|
it 'knows how to time a block of code' do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
expect {
|
7
|
+
time_it 'do something' do
|
8
|
+
(1..10_000_000).each { |k| k * k }
|
9
|
+
'hello'
|
10
|
+
end
|
11
|
+
}.to output(/Ran do something in/i).to_stdout
|
12
12
|
end
|
13
13
|
end
|
data/spec/lib/range_spec.rb
CHANGED
@@ -74,8 +74,10 @@ describe Range do
|
|
74
74
|
|
75
75
|
it 'knows the difference with another range' do
|
76
76
|
# Other is same as self
|
77
|
+
# rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
|
77
78
|
expect(((4..10) - (4..10)).size).to eq(0)
|
78
79
|
expect(((4..10) - (4..10))).to be_empty
|
80
|
+
# rubocop:enable Lint/BinaryOperatorWithIdenticalOperands
|
79
81
|
|
80
82
|
# Other is proper subset of self
|
81
83
|
expect(((4..10) - (6..7)).first).to eq((4..5))
|
@@ -129,7 +131,7 @@ describe Range do
|
|
129
131
|
end
|
130
132
|
|
131
133
|
it 'can determine that overlapping ranges do not span' do
|
132
|
-
expect((0..10)).
|
134
|
+
expect((0..10)).not_to be_spanned_by([(0..3), (3..6), (7..10)])
|
133
135
|
end
|
134
136
|
|
135
137
|
it 'allows spanning ranges to be any Enumerable' do
|
@@ -137,7 +139,7 @@ describe Range do
|
|
137
139
|
set = [(0..3), (4..6), (7..10)].to_set
|
138
140
|
expect((0..10)).to be_spanned_by(set)
|
139
141
|
set = [(0...3), (4..6), (7..10)].to_set
|
140
|
-
expect((0..10)).
|
142
|
+
expect((0..10)).not_to be_spanned_by(set)
|
141
143
|
end
|
142
144
|
|
143
145
|
it 'allows the spanning set to be wider than itself' do
|
@@ -149,20 +151,20 @@ describe Range do
|
|
149
151
|
|
150
152
|
describe 'overlapping a single range' do
|
151
153
|
it 'knows if another range overlaps it' do
|
152
|
-
expect((0..10).
|
153
|
-
expect((0..10).
|
154
|
-
expect((0..10).
|
155
|
-
expect((0..10).
|
156
|
-
expect((0..10).
|
157
|
-
expect((0..10).
|
154
|
+
expect((0..10)).to be_overlaps(-3..5)
|
155
|
+
expect((0..10)).to be_overlaps(3..5)
|
156
|
+
expect((0..10)).to be_overlaps(8..15)
|
157
|
+
expect((0..10)).to be_overlaps(0..10)
|
158
|
+
expect((0..10)).not_to be_overlaps(11..12)
|
159
|
+
expect((0..10)).not_to be_overlaps(-11..-1)
|
158
160
|
|
159
161
|
# Order of operands should not matter
|
160
|
-
expect((-3..5).
|
161
|
-
expect((3..5).
|
162
|
-
expect((8..15).
|
163
|
-
expect((0..10).
|
164
|
-
expect((11..12).
|
165
|
-
expect((-11..-1).
|
162
|
+
expect((-3..5)).to be_overlaps(0..10)
|
163
|
+
expect((3..5)).to be_overlaps(0..10)
|
164
|
+
expect((8..15)).to be_overlaps(0..10)
|
165
|
+
expect((0..10)).to be_overlaps(0..10)
|
166
|
+
expect((11..12)).not_to be_overlaps(0..10)
|
167
|
+
expect((-11..-1)).not_to be_overlaps(0..10)
|
166
168
|
end
|
167
169
|
|
168
170
|
it 'can determine whether a set contains covered overlaps' do
|