Class: Workpattern::Workpattern
- Inherits:
-
Object
- Object
- Workpattern::Workpattern
- Defined in:
- lib/workpattern/workpattern.rb
Overview
Represents the working and resting periods across a given number of whole years. Each Workpatternhas a unique name so it can be easily identified amongst all the other Workpattern objects.
This and the Clock class are the only two that should be referenced by calling applications when using this gem.
Constant Summary collapse
- @@workpatterns =
Holds collection of
Workpatternobjects {}
- @@tz =
Holds local timezone info
nil
Instance Attribute Summary collapse
-
#base ⇒ Object
readonly
Starting year.
-
#from ⇒ Object
readonly
First date in
Workpattern. -
#name ⇒ Object
readonly
Name given to the
Workpattern. -
#span ⇒ Object
readonly
Number of years.
-
#to ⇒ Object
readonly
Last date in
Workpattern. -
#weeks ⇒ Object
readonly
Returns the value of attribute weeks.
Class Method Summary collapse
-
.clear ⇒ Object
Deletes all
Workpatternobjects. -
.delete(name) ⇒ Boolean
Deletes the specific named
Workpatternif it doesn’t. - .from_h(hash, overwrite: false) ⇒ Object
-
.get(name) ⇒ Object
Returns the specific named
Workpatternexist. -
.to_a ⇒ Array
Returns an Array containing all the
Workpatternobjects. - .workpatterns ⇒ Object
Instance Method Summary collapse
-
#calc(start, duration) ⇒ DateTime
Calculates the resulting date when the
durationin minutes is added to thestartdate. -
#diff(start, finish) ⇒ Integer
Returns number of minutes between two dates.
-
#find_weekpattern(date) ⇒ Week
Retrieve the correct
Weekpattern for the supplied date. -
#initialize(name = DEFAULT_WORKPATTERN_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN) ⇒ Workpattern
constructor
The new
Workpatternobject is created with all working minutes. -
#resting(args = {}) ⇒ Object
Convenience method that calls
#workpatternwith the:work_typespecified as resting. -
#timezone ⇒ Object
Retrieves the local timezone.
- #to_h ⇒ Object
-
#to_local(date) ⇒ Object
Converts a date like object into local time.
-
#to_utc(date) ⇒ Object
Converts a date like object into utc.
- #week_pattern ⇒ Object
-
#working(args = {}) ⇒ Object
Convenience method that calls
#workpatternwith the:work_typespecified as working. -
#working?(start) ⇒ Boolean
Returns true if the given minute is working and false if it is resting.
-
#workpattern(opts = {}) ⇒ Object
Applys a working or resting pattern to the
Workpatternobject.
Constructor Details
#initialize(name = DEFAULT_WORKPATTERN_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN) ⇒ Workpattern
The new Workpattern object is created with all working minutes.
31st December.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/workpattern/workpattern.rb', line 64 def initialize(name = DEFAULT_WORKPATTERN_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN) if workpatterns.key?(name) raise(NameError, "Workpattern '#{name}' already exists and can't be created again") end offset = span < 0 ? span.abs - 1 : 0 @name = name @base = base @span = span @from = Time.gm(@base.abs - offset) @to = Time.gm(@from.year + @span.abs - 1, 12, 31, 23, 59) @weeks = SortedSet.new @weeks << Week.new(@from, @to) workpatterns[@name] = self @week_pattern = WeekPattern.new(self) end |
Instance Attribute Details
#base ⇒ Object (readonly)
Starting year
35 |
# File 'lib/workpattern/workpattern.rb', line 35 attr_reader :name, :base, :span, :from, :to, :weeks |
#from ⇒ Object (readonly)
First date in Workpattern
35 |
# File 'lib/workpattern/workpattern.rb', line 35 attr_reader :name, :base, :span, :from, :to, :weeks |
#name ⇒ Object (readonly)
Name given to the Workpattern
35 36 37 |
# File 'lib/workpattern/workpattern.rb', line 35 def name @name end |
#span ⇒ Object (readonly)
Number of years
35 |
# File 'lib/workpattern/workpattern.rb', line 35 attr_reader :name, :base, :span, :from, :to, :weeks |
#to ⇒ Object (readonly)
Last date in Workpattern
35 |
# File 'lib/workpattern/workpattern.rb', line 35 attr_reader :name, :base, :span, :from, :to, :weeks |
#weeks ⇒ Object (readonly)
Returns the value of attribute weeks.
35 |
# File 'lib/workpattern/workpattern.rb', line 35 attr_reader :name, :base, :span, :from, :to, :weeks |
Class Method Details
.clear ⇒ Object
Deletes all Workpattern objects
93 94 95 |
# File 'lib/workpattern/workpattern.rb', line 93 def self.clear workpatterns.clear end |
.delete(name) ⇒ Boolean
Deletes the specific named Workpattern if it doesn’t
119 120 121 |
# File 'lib/workpattern/workpattern.rb', line 119 def self.delete(name) workpatterns.delete(name).nil? ? false : true end |
.from_h(hash, overwrite: false) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/workpattern/workpattern.rb', line 176 def self.from_h(hash, overwrite: false) unless hash.key?(:version) raise ArgumentError, "from_h: hash is missing a :version key " \ "(if deserialising from JSON, use symbolize_names: true)" end unless hash[:version] == 1 raise ArgumentError, "from_h: unsupported version #{hash[:version].inspect} " \ "(supported: 1)" end unless hash[:name].is_a?(String) && !hash[:name].empty? raise ArgumentError, "from_h: :name must be a non-empty String" end unless hash[:base].is_a?(Integer) raise ArgumentError, "from_h: :base must be an Integer" end unless hash[:span].is_a?(Integer) && hash[:span] != 0 raise ArgumentError, "from_h: :span must be a non-zero Integer" end unless hash[:weeks].is_a?(Array) raise ArgumentError, "from_h: :weeks must be an Array" end name = hash[:name] if workpatterns.key?(name) && !overwrite raise NameError, "Workpattern '#{name}' already exists and can't be created again" end wp = allocate wp.instance_variable_set(:@name, name) wp.instance_variable_set(:@base, hash[:base]) wp.instance_variable_set(:@span, hash[:span]) offset = hash[:span] < 0 ? hash[:span].abs - 1 : 0 from_time = Time.gm(hash[:base].abs - offset) to_time = Time.gm(from_time.year + hash[:span].abs - 1, 12, 31, 23, 59) wp.instance_variable_set(:@from, from_time) wp.instance_variable_set(:@to, to_time) weeks = SortedSet.new hash[:weeks].each { |wh| weeks << Week.from_h(wh) } raise ArgumentError, "from_h: :weeks must not be empty" if weeks.empty? wp.instance_variable_set(:@weeks, weeks) wp.instance_variable_set(:@week_pattern, WeekPattern.new(wp)) workpatterns.delete(name) if overwrite workpatterns[name] = wp wp end |
.get(name) ⇒ Object
Returns the specific named Workpattern exist
109 110 111 112 |
# File 'lib/workpattern/workpattern.rb', line 109 def self.get(name) return workpatterns[name] if workpatterns.key?(name) raise(NameError, "Workpattern '#{name}' doesn't exist so can't be retrieved") end |
.to_a ⇒ Array
Returns an Array containing all the Workpattern objects
100 101 102 |
# File 'lib/workpattern/workpattern.rb', line 100 def self.to_a workpatterns.to_a end |
.workpatterns ⇒ Object
18 19 20 |
# File 'lib/workpattern/workpattern.rb', line 18 def self.workpatterns @@workpatterns end |
Instance Method Details
#calc(start, duration) ⇒ DateTime
Calculates the resulting date when the duration in minutes is added to the start date. The duration is always in whole minutes and subtracts from start when it is a negative number.
start
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/workpattern/workpattern.rb', line 235 def calc(start, duration) return start if duration == 0 a_day = SAME_DAY utc_start = to_utc(start) while duration != 0 if a_day == PREVIOUS_DAY utc_start -= DAY a_day = SAME_DAY utc_start = Time.gm(utc_start.year, utc_start.month, utc_start.day,LAST_TIME_IN_DAY.hour, LAST_TIME_IN_DAY.min) week = find_weekpattern(utc_start) if week.working?(utc_start) duration += 1 end else week = find_weekpattern(utc_start) end utc_start, duration, a_day = week.calc(utc_start, duration, a_day) end to_local(utc_start) end |
#diff(start, finish) ⇒ Integer
Returns number of minutes between two dates
276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/workpattern/workpattern.rb', line 276 def diff(start, finish) utc_start = to_utc(start) utc_finish = to_utc(finish) utc_start, utc_finish = utc_finish, utc_start if utc_finish < utc_start minutes = 0 while utc_start != utc_finish week = find_weekpattern(utc_start) r_minutes, utc_start = week.diff(utc_start, utc_finish) minutes += r_minutes end minutes end |
#find_weekpattern(date) ⇒ Week
Retrieve the correct Week pattern for the supplied date.
If the supplied date is outside the span of the Workpattern object then it returns an all working Week object for the calculation.
date in it’s range
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/workpattern/workpattern.rb', line 300 def find_weekpattern(date) # find the pattern that fits the date # if date < @from result = Week.new(Time.at(0), @from - MINUTE, WORK_TYPE) elsif date > to result = Week.new(@to + MINUTE, Time.new(9999), WORK_TYPE) else date = Time.gm(date.year, date.month, date.day) result = @weeks.find { |week| week.start <= date && week.finish >= date } end result end |
#resting(args = {}) ⇒ Object
Convenience method that calls #workpattern with the :work_type specified as resting.
153 154 155 156 |
# File 'lib/workpattern/workpattern.rb', line 153 def resting(args = {}) args[:work_type] = REST_TYPE workpattern(args) end |
#timezone ⇒ Object
Retrieves the local timezone
52 53 54 |
# File 'lib/workpattern/workpattern.rb', line 52 def timezone @@tz || @@tz = TZInfo::Timezone.get(Time.now.zone) end |
#to_h ⇒ Object
168 169 170 171 172 173 174 |
# File 'lib/workpattern/workpattern.rb', line 168 def to_h { version: 1, name: @name, base: @base, span: @span, weeks: @weeks.map(&:to_h) } end |
#to_local(date) ⇒ Object
Converts a date like object into local time
47 48 49 |
# File 'lib/workpattern/workpattern.rb', line 47 def to_local(date) date.to_time.getgm end |
#to_utc(date) ⇒ Object
Converts a date like object into utc
42 43 44 |
# File 'lib/workpattern/workpattern.rb', line 42 def to_utc(date) date.to_time.utc end |
#week_pattern ⇒ Object
82 83 84 |
# File 'lib/workpattern/workpattern.rb', line 82 def week_pattern @week_pattern end |
#working(args = {}) ⇒ Object
Convenience method that calls #workpattern with the :work_type specified as working.
163 164 165 166 |
# File 'lib/workpattern/workpattern.rb', line 163 def working(args = {}) args[:work_type] = WORK_TYPE workpattern(args) end |
#working?(start) ⇒ Boolean
Returns true if the given minute is working and false if it is resting.
265 266 267 268 |
# File 'lib/workpattern/workpattern.rb', line 265 def working?(start) utc_start = to_utc(start) find_weekpattern(utc_start).working?(utc_start) end |
#workpattern(opts = {}) ⇒ Object
Applys a working or resting pattern to the Workpattern object.
The #resting and #working methods are convenience methods that call this with the appropriate :work_type already set.
apply to.It defaults to :all days to apply the pattern. Defaults to 00:00. days to apply the pattern. Defaults to 23:59. Defaults to working.
144 145 146 |
# File 'lib/workpattern/workpattern.rb', line 144 def workpattern(opts = {}) week_pattern.workpattern(opts) end |