weekling 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -0
- data/.gitignore +10 -0
- data/.travis.yml +5 -0
- data/.yardopts +5 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +54 -0
- data/HISTORY.md +6 -0
- data/LICENSE.md +15 -0
- data/README.md +397 -0
- data/Rakefile +47 -0
- data/lib/aef/weekling.rb +45 -0
- data/lib/aef/weekling/core_extensions.rb +28 -0
- data/lib/aef/weekling/core_extensions/to_week_and_week_day.rb +41 -0
- data/lib/aef/weekling/core_extensions/to_year.rb +36 -0
- data/lib/aef/weekling/week.rb +373 -0
- data/lib/aef/weekling/week_day.rb +339 -0
- data/lib/aef/weekling/year.rb +251 -0
- data/lib/weekling.rb +33 -0
- data/lib/weekling/bare.rb +24 -0
- data/spec/aef/weekling/core_extensions_spec.rb +81 -0
- data/spec/aef/weekling/week_day_spec.rb +607 -0
- data/spec/aef/weekling/week_spec.rb +596 -0
- data/spec/aef/weekling/year_spec.rb +378 -0
- data/spec/spec_helper.rb +26 -0
- data/weekling.gemspec +55 -0
- metadata +196 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,339 @@
|
|
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 'aef/weekling'
|
21
|
+
|
22
|
+
module Aef
|
23
|
+
module Weekling
|
24
|
+
|
25
|
+
# Immutable object representing a calendar week day (according to ISO 8601).
|
26
|
+
class WeekDay
|
27
|
+
include Comparable
|
28
|
+
|
29
|
+
# Table to translate symbolic lowercase english day names to day numbers.
|
30
|
+
# @private
|
31
|
+
SYMBOL_TO_INDEX_TABLE = {
|
32
|
+
:monday => 1,
|
33
|
+
:tuesday => 2,
|
34
|
+
:wednesday => 3,
|
35
|
+
:thursday => 4,
|
36
|
+
:friday => 5,
|
37
|
+
:saturday => 6,
|
38
|
+
:sunday => 7
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
# Regular expression for week-day extraction from strings.
|
42
|
+
# @private
|
43
|
+
PARSE_PATTERN = /(0|-?\d+)-W(0[1-9]|(?:1|2|3|4)\d|5(?:0|1|2|3))-([1-7])/
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# Initializes the current week day.
|
47
|
+
#
|
48
|
+
# @return [Aef::Weekling::WeekDay] the current week day
|
49
|
+
def today
|
50
|
+
today = Date.today
|
51
|
+
|
52
|
+
new(today, ((today.wday - 1) % 7) + 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias now today
|
56
|
+
|
57
|
+
# Parses the first week day out of a string.
|
58
|
+
#
|
59
|
+
# @note Looks for patterns like this:
|
60
|
+
# 2011-W03-5
|
61
|
+
# @param [String] string a string containing a week-day representation
|
62
|
+
# @return [Aef::Weekling::WeekDay] the week day parsed from input
|
63
|
+
# @raise [ArgumentError] if pattern cannot be found
|
64
|
+
def parse(string)
|
65
|
+
if sub_matches = PARSE_PATTERN.match(string.to_s)
|
66
|
+
original, year, week_index, day_index = *sub_matches
|
67
|
+
new(year.to_i, week_index.to_i, day_index.to_i)
|
68
|
+
else
|
69
|
+
raise ArgumentError, 'No week day found for parsing'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [Aef::Weekling::Week] the week the day is part of
|
75
|
+
attr_reader :week
|
76
|
+
|
77
|
+
# @return [Integer] the number of the day in its week
|
78
|
+
attr_reader :index
|
79
|
+
|
80
|
+
# @overload initialize(week_day)
|
81
|
+
# Initialize by a week-day-like object.
|
82
|
+
# @param [Aef::Weekling::WeekDay] week_day a week-day-like object
|
83
|
+
#
|
84
|
+
# @overload initialize(date)
|
85
|
+
# Initialize by a date-like object.
|
86
|
+
# @param [Date, DateTime, Time] date a date-like object
|
87
|
+
#
|
88
|
+
# @overload initialize(week, day)
|
89
|
+
# Initialize by week-like-object and a day.
|
90
|
+
# @param [Aef::Weekling::Week] week a week-like object
|
91
|
+
# @param [Integer, Symbol] day either a day number or a lowercase
|
92
|
+
# english day name
|
93
|
+
#
|
94
|
+
# @overload initialize(year, week_index, day)
|
95
|
+
# Initialize by year, week number and day.
|
96
|
+
# @param [Integer, Aef::Weekling::Year] year a year
|
97
|
+
# @param [Integer] week_number a weeks index
|
98
|
+
# @param [Integer, Symbol] day either a day number or a lowercase english day name
|
99
|
+
def initialize(*arguments)
|
100
|
+
case arguments.count
|
101
|
+
when 1
|
102
|
+
object = arguments.first
|
103
|
+
if [:week, :index].all?{|method_name| object.respond_to?(method_name) }
|
104
|
+
@week = object.week.to_week
|
105
|
+
@index = object.index.to_i
|
106
|
+
elsif object.respond_to?(:to_date)
|
107
|
+
date = object.to_date
|
108
|
+
@week = Week.new(date)
|
109
|
+
@index = ((date.wday - 1) % 7) + 1
|
110
|
+
else
|
111
|
+
raise ArgumentError, 'A single argument must either respond to #week and #index or to #to_date'
|
112
|
+
end
|
113
|
+
when 2
|
114
|
+
week, day = *arguments
|
115
|
+
@week = week.to_week
|
116
|
+
if day.respond_to?(:to_i)
|
117
|
+
@index = day.to_i
|
118
|
+
else
|
119
|
+
raise ArgumentError, 'Invalid day symbol' unless @index = SYMBOL_TO_INDEX_TABLE[day.to_sym]
|
120
|
+
end
|
121
|
+
when 3
|
122
|
+
year, week_index, day = *arguments
|
123
|
+
@week = Week.new(year, week_index)
|
124
|
+
if day.respond_to?(:to_i)
|
125
|
+
@index = day.to_i
|
126
|
+
else
|
127
|
+
raise ArgumentError, 'Invalid day symbol' unless @index = SYMBOL_TO_INDEX_TABLE[day.to_sym]
|
128
|
+
end
|
129
|
+
else
|
130
|
+
raise ArgumentError, "wrong number of arguments (#{arguments.count} for 1..3)"
|
131
|
+
end
|
132
|
+
|
133
|
+
raise ArgumentError, 'Index must be in 1..7' unless (1..7).include?(index)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Represents a week-day as String in ISO 8601 format.
|
137
|
+
#
|
138
|
+
# @example Output of friday in 42nd week of 2525
|
139
|
+
# Aef::Weekling::WeekDay.new(2525, 42, 5).to_s
|
140
|
+
# # => "2525-W42-5"
|
141
|
+
#
|
142
|
+
# @return [String] a character representation of the week day
|
143
|
+
def to_s
|
144
|
+
"#{week}-#{index}"
|
145
|
+
end
|
146
|
+
|
147
|
+
# Represents a week-day as String for debugging.
|
148
|
+
#
|
149
|
+
# @example Output of friday in 42nd week of 2525
|
150
|
+
# Aef::Weekling::WeekDay.new(2525, 42, 5)
|
151
|
+
# # => "#<Aef::Weekling::WeekDay: 2525-W42-5>"
|
152
|
+
#
|
153
|
+
# @return [String] a character representation for debugging
|
154
|
+
def inspect
|
155
|
+
"#<#{self.class.name}: #{to_s}>"
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [Symbol] a symbolic representation of the week day
|
159
|
+
def to_sym
|
160
|
+
SYMBOL_TO_INDEX_TABLE.invert[index]
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns the date of the week-day.
|
164
|
+
#
|
165
|
+
# @return [Date] the date of the week-day
|
166
|
+
def to_date
|
167
|
+
date = Date.new(week.year.to_i, 1, 1)
|
168
|
+
|
169
|
+
days_to_add = 7 * week.index
|
170
|
+
days_to_add -= 7 if date.cweek == 1
|
171
|
+
days_to_add -= ((date.wday - 1) % 7) + 1
|
172
|
+
days_to_add += index
|
173
|
+
|
174
|
+
date + days_to_add
|
175
|
+
end
|
176
|
+
|
177
|
+
# @return [Aef::Weekling::WeekDay] self reference
|
178
|
+
def to_week_day
|
179
|
+
self
|
180
|
+
end
|
181
|
+
|
182
|
+
# @param [Aef::Weekling::WeekDay] other a week-day-like object to be compared
|
183
|
+
# @return [true, false] true if other lies in the same week and has the
|
184
|
+
# same index
|
185
|
+
def ==(other)
|
186
|
+
other_week_day = self.class.new(other)
|
187
|
+
|
188
|
+
week == other_week_day.week and index == other_week_day.index
|
189
|
+
end
|
190
|
+
|
191
|
+
# @param [Aef::Weekling::WeekDay] other a week-day object to be compared
|
192
|
+
# @return [true, false] true if other lies in the same year, has the same
|
193
|
+
# index and is of the same or a descending class
|
194
|
+
def eql?(other)
|
195
|
+
other.is_a?(self.class) and self == other
|
196
|
+
end
|
197
|
+
|
198
|
+
# @return [see Array#hash] identity hash for hash table usage
|
199
|
+
def hash
|
200
|
+
[week, index].hash
|
201
|
+
end
|
202
|
+
|
203
|
+
# Compares the week-day with another to determine its relative position.
|
204
|
+
#
|
205
|
+
# @param [Aef::Weekling::WeekDay] other a week-day-like object to be compared
|
206
|
+
# @return [-1, 0, 1] -1 if other is greater, 0 if other is equal and 1 if
|
207
|
+
# other is lesser than self
|
208
|
+
def <=>(other)
|
209
|
+
other_week_day = self.class.new(other)
|
210
|
+
|
211
|
+
week_comparison = week <=> other_week_day.week
|
212
|
+
|
213
|
+
return index <=> other_week_day.index if week_comparison == 0
|
214
|
+
return week_comparison
|
215
|
+
end
|
216
|
+
|
217
|
+
# Finds the following week-day.
|
218
|
+
#
|
219
|
+
# @example The thursday after some wednesday
|
220
|
+
# some_day = Aef::Weekling::WeekDay.new(2013, 33, 3)
|
221
|
+
# some_day.next
|
222
|
+
# # => #<Aef::Weekling::WeekDay: 2013-W33-4>
|
223
|
+
#
|
224
|
+
# @example The week-day after a year's last week-day
|
225
|
+
# last_week_day_in_year = Aef::Weekling::WeekDay.new(1998, 53, 7)
|
226
|
+
# last_week_day_in_year.next
|
227
|
+
# # => #<Aef::Weekling::WeekDay: 1999-W01-1>
|
228
|
+
#
|
229
|
+
# @return [Aef::Weekling::WeekDay] the following week-day
|
230
|
+
def next
|
231
|
+
if index == 7
|
232
|
+
self.class.new(week.next, 1)
|
233
|
+
else
|
234
|
+
self.class.new(week, index + 1)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
alias succ next
|
239
|
+
# Find the previous week-day
|
240
|
+
#
|
241
|
+
# @example The sunday before some monday
|
242
|
+
# some_week = Aef::Weekling::WeekDay.new(1783, 16, 1)
|
243
|
+
# some_week.previous
|
244
|
+
# # => #<Aef::Weekling::WeekDay: 1783-W15-7>
|
245
|
+
#
|
246
|
+
# @example The week-day before first week-day of a year
|
247
|
+
# first_week_in_year = Aef::Weekling::WeekDay.new(2014, 1, 1)
|
248
|
+
# first_week_in_year.previous
|
249
|
+
# # => #<Aef::Weekling::WeekDay: 2013-W52-7>
|
250
|
+
#
|
251
|
+
# @return [Aef::Weekling::WeekDay] the previous week-day
|
252
|
+
def previous
|
253
|
+
if index == 1
|
254
|
+
self.class.new(week.previous, 7)
|
255
|
+
else
|
256
|
+
self.class.new(week, index - 1)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
alias pred previous
|
261
|
+
|
262
|
+
# Adds days to the week-day.
|
263
|
+
#
|
264
|
+
# @example 28 days after 2007-W01-1
|
265
|
+
# Aef::Weekling::WeekDay.new(2007, 1, 1) + 28
|
266
|
+
# # => #<Aef::Weekling::WeekDay: 2007-W05-1>
|
267
|
+
#
|
268
|
+
# @param [Integer] other number of days to add
|
269
|
+
# @return [Aef::Weekling::WeekDay] the resulting week-day
|
270
|
+
def +(other)
|
271
|
+
result = self
|
272
|
+
number = other.to_i
|
273
|
+
|
274
|
+
number.abs.times do
|
275
|
+
if number < 0
|
276
|
+
result = result.previous
|
277
|
+
else
|
278
|
+
result = result.next
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
result
|
283
|
+
end
|
284
|
+
|
285
|
+
# Subtracts days from the week-day.
|
286
|
+
#
|
287
|
+
# @example 5 days before 2012-W45-3
|
288
|
+
# Aef::Weekling::WeekDay.new(2012, 45, 3) - 5
|
289
|
+
# # => #<Aef::Weekling::WeekDay: 2012-W44-5>
|
290
|
+
#
|
291
|
+
# @param [Integer] other number of days to subtract
|
292
|
+
# @return [Aef::Weekling::WeekDay] the resulting week-day
|
293
|
+
def -(other)
|
294
|
+
self + -other.to_i
|
295
|
+
end
|
296
|
+
|
297
|
+
# @return [true, false] true if week day is monday
|
298
|
+
def monday?
|
299
|
+
to_sym == :monday
|
300
|
+
end
|
301
|
+
|
302
|
+
# @return [true, false] true if week day is tuesday
|
303
|
+
def tuesday?
|
304
|
+
to_sym == :tuesday
|
305
|
+
end
|
306
|
+
|
307
|
+
# @return [true, false] true if week day is wednesday
|
308
|
+
def wednesday?
|
309
|
+
to_sym == :wednesday
|
310
|
+
end
|
311
|
+
|
312
|
+
# @return [true, false] true if week day is thursday
|
313
|
+
def thursday?
|
314
|
+
to_sym == :thursday
|
315
|
+
end
|
316
|
+
|
317
|
+
# @return [true, false] true if week day is friday
|
318
|
+
def friday?
|
319
|
+
to_sym == :friday
|
320
|
+
end
|
321
|
+
|
322
|
+
# @return [true, false] true if week day is saturday
|
323
|
+
def saturday?
|
324
|
+
to_sym == :saturday
|
325
|
+
end
|
326
|
+
|
327
|
+
# @return [true, false] true if week day is sunday
|
328
|
+
def sunday?
|
329
|
+
to_sym == :sunday
|
330
|
+
end
|
331
|
+
|
332
|
+
# @return [true, false] true if week day is saturday or sunday
|
333
|
+
def weekend?
|
334
|
+
saturday? or sunday?
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
@@ -0,0 +1,251 @@
|
|
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 'aef/weekling'
|
21
|
+
|
22
|
+
module Aef
|
23
|
+
module Weekling
|
24
|
+
|
25
|
+
# Immutable object representing a calendar year (according to ISO 8601).
|
26
|
+
class Year
|
27
|
+
include Comparable
|
28
|
+
|
29
|
+
# Regular expression for Year extraction from strings.
|
30
|
+
# @private
|
31
|
+
PARSE_PATTERN = /(0|-?\d+)/
|
32
|
+
|
33
|
+
class << self
|
34
|
+
# Initializes the current year.
|
35
|
+
#
|
36
|
+
# @return [Aef::Weekling::Year] the current year
|
37
|
+
def today
|
38
|
+
today = Date.today
|
39
|
+
|
40
|
+
new(today.year)
|
41
|
+
end
|
42
|
+
|
43
|
+
alias now today
|
44
|
+
|
45
|
+
# Parses the first year out of a string.
|
46
|
+
#
|
47
|
+
# @note Looks for patterns like this:
|
48
|
+
# 2011
|
49
|
+
# @param [String] string a string containing a year representation
|
50
|
+
# @return [Aef::Weekling::Year] the year parsed from input
|
51
|
+
# @raise [ArgumentError] if pattern cannot be found
|
52
|
+
def parse(string)
|
53
|
+
if sub_matches = PARSE_PATTERN.match(string.to_s)
|
54
|
+
original, year = *sub_matches
|
55
|
+
new(year.to_i)
|
56
|
+
else
|
57
|
+
raise ArgumentError, 'No year found for parsing'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Integer] the number of the year
|
63
|
+
attr_reader :index
|
64
|
+
|
65
|
+
# @overload initialize(index)
|
66
|
+
# Initialize by number.
|
67
|
+
# @param [Integer] index the year's number
|
68
|
+
#
|
69
|
+
# @overload initialize(date)
|
70
|
+
# Initialize by a date-like object.
|
71
|
+
# @param [Date, DateTime, Time] date a date-like object
|
72
|
+
def initialize(index_or_date)
|
73
|
+
if index_or_date.respond_to?(:to_date)
|
74
|
+
date = index_or_date.to_date
|
75
|
+
@index = date.year
|
76
|
+
elsif index_or_date.respond_to?(:to_i)
|
77
|
+
@index = index_or_date.to_i
|
78
|
+
else
|
79
|
+
raise ArgumentError, 'A single argument must either respond to #to_date or to #to_i'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Represents the year as Integer.
|
84
|
+
#
|
85
|
+
# @return [Integer] the year's number
|
86
|
+
def to_i
|
87
|
+
@index
|
88
|
+
end
|
89
|
+
|
90
|
+
# Represents the year as String in ISO 8601 format.
|
91
|
+
#
|
92
|
+
# @example Output of the year 2012
|
93
|
+
# Aef::Weekling::Year.new(2012).to_s
|
94
|
+
# # => "2012"
|
95
|
+
#
|
96
|
+
# @return [String] a character representation of the year
|
97
|
+
def to_s
|
98
|
+
@index.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
# Represents a week as String for debugging.
|
102
|
+
#
|
103
|
+
# @example Output of the year 2012
|
104
|
+
# Aef::Weekling::Year.new(2012).inspect
|
105
|
+
# # => "<#Aef::Weekling::Year: 2012>"
|
106
|
+
def inspect
|
107
|
+
"#<#{self.class.name}: #{to_s}>"
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Aef::Weekling::Year] self reference
|
111
|
+
def to_year
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param [Aef::Weekling::Year] other a year-like object to be compared
|
116
|
+
# @return [true, false] true if other has the same index
|
117
|
+
def ==(other)
|
118
|
+
other_year = self.class.new(other)
|
119
|
+
|
120
|
+
self.index == other_year.index
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param [Aef::Weekling::Year] other a year object to be compared
|
124
|
+
# @return [true, false] true if other has the same index and is of the
|
125
|
+
# same or descending class
|
126
|
+
def eql?(other)
|
127
|
+
self == other and other.is_a?(self.class)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @return [see Integer#hash] identity hash for hash table usage
|
131
|
+
def hash
|
132
|
+
@index.hash
|
133
|
+
end
|
134
|
+
|
135
|
+
# Compares the year with another to determine its relative position.
|
136
|
+
#
|
137
|
+
# @param [Aef::Weekling::Year] other a year-like object to be compared
|
138
|
+
# @return [-1, 0, 1] -1 if other is greater, 0 if other is equal and 1 if
|
139
|
+
# other is lesser than self
|
140
|
+
def <=>(other)
|
141
|
+
other_year = other.to_year
|
142
|
+
|
143
|
+
self.index <=> other_year.index
|
144
|
+
end
|
145
|
+
|
146
|
+
# Finds the following year.
|
147
|
+
#
|
148
|
+
# @example The year after some other year
|
149
|
+
# some_year = Aef::Weekling::Year.new(2012)
|
150
|
+
# some_year.next
|
151
|
+
# # => #<Aef::Weekling::Year: 2013>
|
152
|
+
#
|
153
|
+
# @return [Aef::Weekling::Year] the following year
|
154
|
+
def next
|
155
|
+
self.class.new(@index + 1)
|
156
|
+
end
|
157
|
+
|
158
|
+
alias succ next
|
159
|
+
|
160
|
+
# Finds the previous year.
|
161
|
+
#
|
162
|
+
# @example The year before some other year
|
163
|
+
# some_year = Aef::Weekling::Year.new(2012)
|
164
|
+
# some_year.previous
|
165
|
+
# # => #<Aef::Weekling::Year: 2011>
|
166
|
+
#
|
167
|
+
# @return [Aef::Weekling::Year] the previous year
|
168
|
+
def previous
|
169
|
+
self.class.new(@index - 1)
|
170
|
+
end
|
171
|
+
|
172
|
+
alias pred previous
|
173
|
+
|
174
|
+
# Adds years to the year.
|
175
|
+
#
|
176
|
+
# @example 3 year after 2000
|
177
|
+
# Aef::Weekling::Year.new(2000) + 3
|
178
|
+
# # => #<Aef::Weekling::Year: 2003>
|
179
|
+
#
|
180
|
+
# @param [Integer] other number of years to add
|
181
|
+
# @return [Aef::Weekling::Year] the resulting year
|
182
|
+
def +(other)
|
183
|
+
self.class.new(@index + other.to_i)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Subtracts years from the year.
|
187
|
+
#
|
188
|
+
# @example 3 before 2000
|
189
|
+
# Aef::Weekling::Year.new(2000) - 3
|
190
|
+
# # => #<Aef::Weekling::Year: 1997>
|
191
|
+
#
|
192
|
+
# @param [Integer] other number of years to subtract
|
193
|
+
# @return [Aef::Weekling::Year] the resulting year
|
194
|
+
def -(other)
|
195
|
+
self.class.new(@index - other.to_i)
|
196
|
+
end
|
197
|
+
|
198
|
+
# States if the year's index is odd.
|
199
|
+
#
|
200
|
+
# @return [true, false] true if the year is odd
|
201
|
+
def odd?
|
202
|
+
@index.odd?
|
203
|
+
end
|
204
|
+
|
205
|
+
# States if the year's index is even.
|
206
|
+
#
|
207
|
+
# @return [true, false] true if the year is even
|
208
|
+
def even?
|
209
|
+
@index.even?
|
210
|
+
end
|
211
|
+
|
212
|
+
# States if the year is a leap year.
|
213
|
+
#
|
214
|
+
# @return [true, false] true is the year is a leap year
|
215
|
+
def leap?
|
216
|
+
Date.leap?(to_i)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Calculates the amount of weeks in year.
|
220
|
+
#
|
221
|
+
# @example Acquire the amount of weeks for 2015
|
222
|
+
# Aef::Weekling::Year.new(2015).week_count
|
223
|
+
# # => 53
|
224
|
+
#
|
225
|
+
# @return [Integer] the amount of weeks
|
226
|
+
def week_count
|
227
|
+
date = Date.new(index, 12, 31)
|
228
|
+
|
229
|
+
date = date - 7 if date.cweek == 1
|
230
|
+
|
231
|
+
date.cweek
|
232
|
+
end
|
233
|
+
|
234
|
+
# Finds a week in the year.
|
235
|
+
#
|
236
|
+
# @param [Integer] index the week's index
|
237
|
+
# @return [Aef::Weekling::Week] the week in year with the given index
|
238
|
+
def week(index)
|
239
|
+
Week.new(self, index.to_i)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Returns a range of all weeks in year.
|
243
|
+
#
|
244
|
+
# @return [Range<Aef::Weekling::Week>] all weeks in year
|
245
|
+
def weeks
|
246
|
+
week(1)..week(week_count)
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|