weekling 1.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.
@@ -0,0 +1,596 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright Alexander E. Fischer <aef@raxys.net>, 2012
4
+
5
+ This file is part of Weekling.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'spec_helper'
21
+ require 'aef/weekling/week'
22
+ require 'ostruct'
23
+
24
+ describe Aef::Weekling::Week do
25
+ [:today, :now].each do |method|
26
+ context ".#{method}" do
27
+ it "should find the current week" do
28
+ week = described_class.method(method).call
29
+ today = Date.today
30
+
31
+ week.year.should eql Aef::Weekling::Year.new(today.year)
32
+ week.index.should eql today.cweek
33
+ end
34
+ end
35
+ end
36
+
37
+ context ".parse" do
38
+ it "should recognize an ancient week" do
39
+ week = described_class.parse('-1503-W50')
40
+
41
+ week.year.should eql Aef::Weekling::Year.new(-1503)
42
+ week.index.should eql 50
43
+ end
44
+
45
+ it "should recognize a normal week" do
46
+ week = described_class.parse('2011-W30')
47
+
48
+ week.year.should eql Aef::Weekling::Year.new(2011)
49
+ week.index.should eql 30
50
+ end
51
+
52
+ it "should recognize a post apocalyptic week" do
53
+ week = described_class.parse('50023-W03')
54
+
55
+ week.year.should eql Aef::Weekling::Year.new(50023)
56
+ week.index.should eql 3
57
+ end
58
+
59
+ it "should report being unable to parse the given String" do
60
+ lambda{
61
+ described_class.parse('no week!')
62
+ }.should raise_error(ArgumentError, 'No week found for parsing')
63
+ end
64
+ end
65
+
66
+ context ".new" do
67
+ it "should complain about a param of invalid type" do
68
+ lambda {
69
+ described_class.new(123)
70
+ }.should raise_error(ArgumentError, 'A single argument must either respond to #year and #index or to #to_date')
71
+ end
72
+
73
+ it "should complain about less than one argument" do
74
+ lambda {
75
+ described_class.new
76
+ }.should raise_error(ArgumentError, 'wrong number of arguments (0 for 1..2)')
77
+ end
78
+
79
+ it "should complain about more than two arguments" do
80
+ lambda {
81
+ described_class.new(123, 456, 789)
82
+ }.should raise_error(ArgumentError, 'wrong number of arguments (3 for 1..2)')
83
+ end
84
+
85
+ it "should be able to initialize an ancient week by year and index" do
86
+ week = described_class.new(-1691, 11)
87
+
88
+ week.year.should eql Aef::Weekling::Year.new(-1691)
89
+ week.index.should eql 11
90
+ end
91
+
92
+ it "should be able to initialize a normal week by year and index" do
93
+ week = described_class.new(2012, 40)
94
+
95
+ week.year.should eql Aef::Weekling::Year.new(2012)
96
+ week.index.should eql 40
97
+ end
98
+
99
+ it "should be able to initialize a post apocalyptic week by year and index" do
100
+ week = described_class.new(23017, 29)
101
+
102
+ week.year.should eql Aef::Weekling::Year.new(23017)
103
+ week.index.should eql 29
104
+ end
105
+
106
+ it "should be able to initialize a week by a given Week object" do
107
+ old_week = described_class.new(2011, 30)
108
+ week = described_class.new(old_week)
109
+
110
+ week.year.should eql old_week.year
111
+ week.index.should eql old_week.index
112
+ end
113
+
114
+ it "should be able to initialize a week by a given Date object" do
115
+ date = Date.today
116
+ week = described_class.new(date)
117
+
118
+ week.year.should eql Aef::Weekling::Year.new(date.year)
119
+ week.index.should eql date.cweek
120
+ end
121
+
122
+ it "should be able to initialize a week by a given DateTime object" do
123
+ date = DateTime.now
124
+ week = described_class.new(date)
125
+
126
+ week.year.should eql Aef::Weekling::Year.new(date.year)
127
+ week.index.should eql date.cweek
128
+ end
129
+
130
+ it "should be able to initialize a week by a given Time object" do
131
+ time = Time.now
132
+ week = described_class.new(time)
133
+
134
+ date = time.to_date
135
+
136
+ week.year.should eql Aef::Weekling::Year.new(date.year)
137
+ week.index.should eql date.cweek
138
+ end
139
+
140
+ it "should accept week 53 for year in which one exists" do
141
+ lambda{
142
+ described_class.new(2015, 53)
143
+ }.should_not raise_error
144
+ end
145
+
146
+ it "should report week 53 doesn't exist in the given year" do
147
+ lambda{
148
+ described_class.new(2011, 53)
149
+ }.should raise_error(ArgumentError, /Index .* is invalid. Year .* has only 52 weeks/)
150
+ end
151
+
152
+ it "should always report if weeks below index 1 are given" do
153
+ lambda{
154
+ described_class.new(2011, 0)
155
+ }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
156
+ end
157
+
158
+ it "should always report if weeks above index 53 are given" do
159
+ lambda{
160
+ described_class.new(2011, 54)
161
+ }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
162
+ end
163
+ end
164
+
165
+ context "#== (type independent equality)" do
166
+ it "should be true if year and index match" do
167
+ week = described_class.new(2012, 1)
168
+ other = described_class.new(2012, 1)
169
+
170
+ week.should == other
171
+ end
172
+
173
+ it "should be true if year and index match, independent of the other object's type" do
174
+ week = described_class.new(2012, 1)
175
+
176
+ other = OpenStruct.new
177
+ other.year = Aef::Weekling::Year.new(2012)
178
+ other.index = 1
179
+
180
+ week.should == other
181
+ end
182
+
183
+ it "should be false if year matches but not index" do
184
+ week = described_class.new(2012, 1)
185
+ other = described_class.new(2012, 13)
186
+
187
+ week.should_not == other
188
+ end
189
+
190
+ it "should be false if year matches but not index, independent of the other object's type" do
191
+ week = described_class.new(2012, 1)
192
+
193
+ other = OpenStruct.new
194
+ other.year = Aef::Weekling::Year.new(2012)
195
+ other.index = 13
196
+
197
+ week.should_not == other
198
+ end
199
+
200
+ it "should be false if index matches but not year" do
201
+ week = described_class.new(2012, 1)
202
+ other = described_class.new(2005, 1)
203
+
204
+ week.should_not == other
205
+ end
206
+
207
+ it "should be false if index matches but not year, independent of the other object's type" do
208
+ week = described_class.new(2012, 1)
209
+
210
+ other = OpenStruct.new
211
+ other.year = Aef::Weekling::Year.new(2005)
212
+ other.index = 1
213
+
214
+ week.should_not == other
215
+ end
216
+
217
+ it "should be false if both index and year do not match" do
218
+ week = described_class.new(2012, 1)
219
+ other = described_class.new(2005, 13)
220
+
221
+ week.should_not == other
222
+ end
223
+
224
+ it "should be false if both index and year do not match, independent of the other object's type" do
225
+ week = described_class.new(2012, 1)
226
+
227
+ other = OpenStruct.new
228
+ other.year = Aef::Weekling::Year.new(2005)
229
+ other.index = 13
230
+
231
+ week.should_not == other
232
+ end
233
+ end
234
+
235
+ context "#eql? (type dependant equality)" do
236
+ it "should be true if year and index and type matches and of same class" do
237
+ week = described_class.new(2012, 1)
238
+ other = described_class.new(2012, 1)
239
+
240
+ week.should eql other
241
+ end
242
+
243
+ it "should be true if year and index and type matches and of inheriting class" do
244
+ week = described_class.new(2012, 1)
245
+
246
+ inheriting_class = Class.new(described_class)
247
+
248
+ other = inheriting_class.new(2012, 1)
249
+
250
+ week.should eql other
251
+ end
252
+
253
+ it "should be false if year and index match but type differs" do
254
+ week = described_class.new(2012, 1)
255
+
256
+ other = OpenStruct.new
257
+ other.year = Aef::Weekling::Year.new(2012)
258
+ other.index = 1
259
+
260
+ week.should_not eql other
261
+ end
262
+
263
+ it "should be false if year matches but not index" do
264
+ week = described_class.new(2012, 1)
265
+ other = described_class.new(2012, 13)
266
+
267
+ week.should_not eql other
268
+ end
269
+
270
+ it "should be false if index matches but not year" do
271
+ week = described_class.new(2012, 1)
272
+ other = described_class.new(2005, 1)
273
+
274
+ week.should_not eql other
275
+ end
276
+
277
+ it "should be false if both index and year do not match" do
278
+ week = described_class.new(2012, 1)
279
+ other = described_class.new(2005, 13)
280
+
281
+ week.should_not eql other
282
+ end
283
+ end
284
+
285
+ context "#hash" do
286
+ it "should return Integers" do
287
+ a_week = described_class.new(2012, 5)
288
+ another_week = described_class.new(2012, 6)
289
+
290
+ a_week.hash.should be_a(Integer)
291
+ another_week.hash.should be_a(Integer)
292
+ end
293
+
294
+ it "should discriminate a week from another one" do
295
+ a_week = described_class.new(2012, 5)
296
+ another_week = described_class.new(2012, 6)
297
+
298
+ a_week.hash.should_not == another_week.hash
299
+ end
300
+ end
301
+
302
+ context "#<=>" do
303
+ it "should correctly determine the order of weeks based on year" do
304
+ lower_week = described_class.new(2011, 14)
305
+ higher_week = described_class.new(2012, 14)
306
+
307
+ lower_week.should < higher_week
308
+ end
309
+
310
+ it "should correctly determine the order of weeks based on year, independent of type" do
311
+ lower_week = described_class.new(2011, 14)
312
+
313
+ higher_week = OpenStruct.new
314
+ higher_week.year = Aef::Weekling::Year.new(2012)
315
+ higher_week.index = 14
316
+
317
+ lower_week.should < higher_week
318
+ end
319
+
320
+ it "should correctly determine the order of weeks based on index" do
321
+ lower_week = described_class.new(2011, 14)
322
+ higher_week = described_class.new(2011, 15)
323
+
324
+ lower_week.should < higher_week
325
+ end
326
+
327
+ it "should correctly determine the order of weeks based on index, independent of type" do
328
+ lower_week = described_class.new(2011, 14)
329
+
330
+ higher_week = OpenStruct.new
331
+ higher_week.year = Aef::Weekling::Year.new(2011)
332
+ higher_week.index = 15
333
+
334
+ lower_week.should < higher_week
335
+ end
336
+
337
+ it "should prioritize the order years when determining the order of weeks" do
338
+ lower_week = described_class.new(2011, 14)
339
+ higher_week = described_class.new(2012, 13)
340
+
341
+ lower_week.should < higher_week
342
+ end
343
+
344
+ it "should prioritize the order years when determining the order of weeks, independent of type" do
345
+ lower_week = described_class.new(2011, 14)
346
+
347
+ higher_week = OpenStruct.new
348
+ higher_week.year = Aef::Weekling::Year.new(2012)
349
+ higher_week.index = 13
350
+
351
+ lower_week.should < higher_week
352
+ end
353
+ end
354
+
355
+ context "#to_s" do
356
+ it "should be able to display an ancient week" do
357
+ week = described_class.new(-1503, 50)
358
+
359
+ week.to_s.should eql '-1503-W50'
360
+ end
361
+
362
+ it "should be able to display a normal week" do
363
+ week = described_class.new(2011, 30)
364
+
365
+ week.to_s.should eql '2011-W30'
366
+ end
367
+
368
+ it "should be able to display a post apocalyptic week" do
369
+ week = described_class.new(50023, 3)
370
+
371
+ week.to_s.should eql '50023-W03'
372
+ end
373
+ end
374
+
375
+ context "#inspect" do
376
+ it "should be able to display an ancient week" do
377
+ week = described_class.new(-1503, 50)
378
+
379
+ week.inspect.should eql '#<Aef::Weekling::Week: -1503-W50>'
380
+ end
381
+
382
+ it "should be able to display a normal week" do
383
+ week = described_class.new(2011, 30)
384
+
385
+ week.inspect.should eql '#<Aef::Weekling::Week: 2011-W30>'
386
+ end
387
+
388
+ it "should be able to display a post apocalyptic week" do
389
+ week = described_class.new(50023, 3)
390
+
391
+ week.inspect.should eql '#<Aef::Weekling::Week: 50023-W03>'
392
+ end
393
+ end
394
+
395
+ context "#to_week" do
396
+ it "should return itself" do
397
+ week = described_class.new(2011, 30)
398
+ week.to_week.should equal(week)
399
+ end
400
+ end
401
+
402
+ [:next, :succ].each do |method|
403
+ context "##{method}" do
404
+ it "should return the next week" do
405
+ described_class.new(2011, 19).method(method).call.should eql described_class.new(2011, 20)
406
+ end
407
+
408
+ it "should return the next week at the end of a year" do
409
+ described_class.new(2011, 52).method(method).call.should eql described_class.new(2012, 1)
410
+ end
411
+
412
+ it "should return the next week one week before the end of a year with 53 weeks" do
413
+ described_class.new(2015, 52).method(method).call.should eql described_class.new(2015, 53)
414
+ end
415
+
416
+ it "should return the next week at the end of a year with 53 weeks" do
417
+ described_class.new(2015, 53).method(method).call.should eql described_class.new(2016, 1)
418
+ end
419
+ end
420
+ end
421
+
422
+ [:previous, :pred].each do |method|
423
+ context "##{method}" do
424
+ it "should return the previous week" do
425
+ described_class.new(2011, 20).method(method).call.should eql described_class.new(2011, 19)
426
+ end
427
+
428
+ it "should return the previous week at the beginning of a year" do
429
+ described_class.new(2012, 1).method(method).call.should eql described_class.new(2011, 52)
430
+ end
431
+
432
+ it "should return the previous week at the beginning of a year after one with 53 weeks" do
433
+ described_class.new(2016, 1).method(method).call.should eql described_class.new(2015, 53)
434
+ end
435
+
436
+ it "should return the previous week at the end of a year with 53 weeks" do
437
+ described_class.new(2015, 53).method(method).call.should eql described_class.new(2015, 52)
438
+ end
439
+ end
440
+ end
441
+
442
+ context "#+" do
443
+ it "should be able to add a positive amount of weeks" do
444
+ (described_class.new(1998, 10) + 15).should eql described_class.new(1998, 25)
445
+ end
446
+
447
+ it "should be able to add a positive amount of weeks so that the result isn't in the year anymore" do
448
+ (described_class.new(1996, 48) + 8).should eql described_class.new(1997, 4)
449
+ end
450
+
451
+ it "should be able to add a positive amount of weeks so that the result isn't in the year with 53 weeks anymore" do
452
+ (described_class.new(2004, 48) + 8).should eql described_class.new(2005, 3)
453
+ end
454
+
455
+ it "should be able to add a negative amount of weeks" do
456
+ (described_class.new(1998, 20) + -15).should eql described_class.new(1998, 5)
457
+ end
458
+
459
+ it "should be able to add a negative amount of weeks so that the result isn't in the year anymore" do
460
+ (described_class.new(1998, 10) + -12).should eql described_class.new(1997, 50)
461
+ end
462
+
463
+ it "should be able to add a negative amount of weeks so that the result is in the previous year which has 53 weeks" do
464
+ (described_class.new(2005, 23) + -25).should eql described_class.new(2004, 51)
465
+ end
466
+ end
467
+
468
+ context "#-" do
469
+ it "should be able to subtract a positive amount of weeks" do
470
+ (described_class.new(1998, 37) - 15).should eql described_class.new(1998, 22)
471
+ end
472
+
473
+ it "should be able to subtract a positive amount of weeks so that the result isn't in the year anymore" do
474
+ (described_class.new(1998, 48) - 53).should eql described_class.new(1997, 47)
475
+ end
476
+
477
+ it "should be able to subtract a positive amount of weeks so that the result is in the previous year which has 53 weeks" do
478
+ (described_class.new(2005, 16) - 32).should eql described_class.new(2004, 37)
479
+ end
480
+
481
+ it "should be able to subtract a negative amount of weeks" do
482
+ (described_class.new(1998, 20) - -15).should eql described_class.new(1998, 35)
483
+ end
484
+
485
+ it "should be able to subtract a negative amount of weeks so that the result isn't in the year anymore" do
486
+ (described_class.new(1996, 40) - -23).should eql described_class.new(1997, 11)
487
+ end
488
+
489
+ it "should be able to subtract a negative amount of weeks so that the result isn't in the year with 53 weeks anymore" do
490
+ (described_class.new(2004, 49) - -31).should eql described_class.new(2005, 27)
491
+ end
492
+ end
493
+
494
+ context "#until_index" do
495
+ it "should return a range ending in the current year if the given index is greater to the weeks index" do
496
+ week = described_class.new(2011, 13)
497
+
498
+ week.until_index(46).should eql (week .. described_class.new(2011, 46))
499
+ end
500
+
501
+ it "should return a range ending in the next year if the given index is equal to the weeks index" do
502
+ week = described_class.new(2011, 13)
503
+
504
+ week.until_index(13).should eql (week .. described_class.new(2012, 13))
505
+ end
506
+
507
+ it "should return a range ending in the next year if the given index is equal to the weeks index" do
508
+ week = described_class.new(2011, 13)
509
+
510
+ week.until_index(3).should eql (week .. described_class.new(2012, 3))
511
+ end
512
+ end
513
+
514
+ context "#even?" do
515
+ it "should be true if the index is even" do
516
+ described_class.new(420, 6).should be_even
517
+ described_class.new(2011, 42).should be_even
518
+ described_class.new(25043, 28).should be_even
519
+ end
520
+
521
+ it "should be false if the index is odd" do
522
+ described_class.new(420, 7).should_not be_even
523
+ described_class.new(2011, 43).should_not be_even
524
+ described_class.new(25043, 29).should_not be_even
525
+ end
526
+ end
527
+
528
+ context "#odd?" do
529
+ it "should be true if the index is odd" do
530
+ described_class.new(420, 7).should be_odd
531
+ described_class.new(2011, 43).should be_odd
532
+ described_class.new(25043, 29).should be_odd
533
+ end
534
+
535
+ it "should be false if the index is even" do
536
+ described_class.new(420, 6).should_not be_odd
537
+ described_class.new(2011, 42).should_not be_odd
538
+ described_class.new(25043, 28).should_not be_odd
539
+ end
540
+ end
541
+
542
+ context "#days" do
543
+ it "should return a range of the weeks days" do
544
+ described_class.new(2011, 15).days.should eql(
545
+ (Aef::Weekling::WeekDay.new(2011, 15, 1)..Aef::Weekling::WeekDay.new(2011, 15, 7)))
546
+ end
547
+ end
548
+
549
+ context "#day" do
550
+ it "should return a day by index" do
551
+ described_class.new(2011, 15).day(1).should eql Aef::Weekling::WeekDay.new(2011, 15, 1)
552
+ end
553
+
554
+ it "should return a day by symbol" do
555
+ described_class.new(2011, 15).day(:friday).should eql Aef::Weekling::WeekDay.new(2011, 15, 5)
556
+ end
557
+ end
558
+
559
+ context "weekday methods" do
560
+ before(:all) do
561
+ @week = described_class.new(2011, 17)
562
+ end
563
+
564
+ it "should deliver monday" do
565
+ @week.monday.should eql Aef::Weekling::WeekDay.new(@week, 1)
566
+ end
567
+
568
+ it "should deliver tuesday" do
569
+ @week.tuesday.should eql Aef::Weekling::WeekDay.new(@week, 2)
570
+ end
571
+
572
+ it "should deliver wednesday" do
573
+ @week.wednesday.should eql Aef::Weekling::WeekDay.new(@week, 3)
574
+ end
575
+
576
+ it "should deliver thursday" do
577
+ @week.thursday.should eql Aef::Weekling::WeekDay.new(@week, 4)
578
+ end
579
+
580
+ it "should deliver friday" do
581
+ @week.friday.should eql Aef::Weekling::WeekDay.new(@week, 5)
582
+ end
583
+
584
+ it "should deliver saturday" do
585
+ @week.saturday.should eql Aef::Weekling::WeekDay.new(@week, 6)
586
+ end
587
+
588
+ it "should deliver sunday" do
589
+ @week.sunday.should eql Aef::Weekling::WeekDay.new(@week, 7)
590
+ end
591
+
592
+ it "should deliver the weekend" do
593
+ @week.weekend.should eql [Aef::Weekling::WeekDay.new(@week, 6), Aef::Weekling::WeekDay.new(@week, 7)]
594
+ end
595
+ end
596
+ end