workpattern 0.5.0 → 0.7.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,142 @@
1
+ module Workpattern
2
+ class WeekPattern
3
+ def initialize(work_pattern)
4
+ @work_pattern = work_pattern
5
+ end
6
+
7
+ def work_pattern
8
+ @work_pattern
9
+ end
10
+
11
+ def weeks
12
+ work_pattern.weeks
13
+ end
14
+
15
+ def from
16
+ work_pattern.from
17
+ end
18
+
19
+ def to
20
+ work_pattern.to
21
+ end
22
+ # Applys a working or resting pattern to the <tt>Workpattern</tt> object.
23
+ #
24
+ # The #resting and #working methods are convenience methods that call
25
+ # this with the appropriate <tt>:work_type</tt> already set.
26
+ #
27
+ # @param [Hash] opts the options used to apply a workpattern
28
+ # @option opts [Date] :start The first date to apply the pattern. Defaults
29
+ # to the <tt>start</tt> attribute.
30
+ # @option opts [Date] :finish The last date to apply the pattern. Defaults
31
+ # to the <tt>finish</tt> attribute.
32
+ # @option opts [DAYNAMES] :days The specific day or days the pattern will
33
+ # apply to.It defaults to <tt>:all</tt>
34
+ # @option opts [(#hour, #min)] :start_time The first time in the selected
35
+ # days to apply the pattern. Defaults to <tt>00:00</tt>.
36
+ # @option opts [(#hour, #min)] :finish_time The last time in the selected
37
+ # days to apply the pattern. Defaults to <tt>23:59</tt>.
38
+ # @option opts [(WORK_TYPE || REST_TYPE)] :work_type Either working or resting.
39
+ # Defaults to working.
40
+ # @see #working
41
+ # @see #resting
42
+ #
43
+ def workpattern(opts = {})
44
+ args = all_workpattern_options(opts)
45
+
46
+ args = standardise_args(args)
47
+
48
+ upd_start = work_pattern.to_utc(args[:start])
49
+ upd_finish = work_pattern.to_utc(args[:finish])
50
+
51
+ while upd_start <= upd_finish
52
+
53
+ current_wp = work_pattern.find_weekpattern(upd_start)
54
+
55
+ if current_wp.start == upd_start
56
+ if current_wp.finish > upd_finish
57
+ clone_wp = fetch_updatable_week_pattern(current_wp,
58
+ upd_finish + DAY,
59
+ current_wp.finish,
60
+ upd_start,
61
+ upd_finish)
62
+ update_and_store_week_pattern(clone_wp, args)
63
+ upd_start = upd_finish + DAY
64
+ else # (current_wp.finish == upd_finish)
65
+ current_wp.workpattern(args[:days], args[:from_time],
66
+ args[:to_time], args[:work_type])
67
+ upd_start = current_wp.finish + DAY
68
+ end
69
+ else
70
+ clone_wp = fetch_updatable_week_pattern(current_wp, current_wp.start,
71
+ upd_start - DAY, upd_start)
72
+ if clone_wp.finish > upd_finish
73
+ after_wp = fetch_updatable_week_pattern(clone_wp,
74
+ upd_start,
75
+ upd_finish,
76
+ upd_finish + DAY)
77
+ weeks << after_wp
78
+ end
79
+ update_and_store_week_pattern(clone_wp, args)
80
+ upd_start = clone_wp.finish + DAY
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def all_workpattern_options(opts)
88
+
89
+ args = { start: from, finish: to, days: :all,
90
+ from_time: FIRST_TIME_IN_DAY, to_time: LAST_TIME_IN_DAY,
91
+ work_type: WORK_TYPE }
92
+
93
+ args.merge! opts
94
+ end
95
+
96
+ def standardise_args(args)
97
+
98
+ args[:start] = dmy_date(args[:start])
99
+ args[:finish] = dmy_date(args[:finish])
100
+
101
+ args
102
+ end
103
+
104
+ # Clones the supplied Week Pattern then changes the dates on it
105
+ # The newly cloned Week pattern dates are also changed and it is
106
+ # returned by this method
107
+ #
108
+ def fetch_updatable_week_pattern(keep_week, keep_start, keep_finish,
109
+ change_start, change_finish = nil)
110
+ change_week = keep_week.duplicate
111
+ adjust_date_range(keep_week, keep_start, keep_finish)
112
+ if change_finish.nil?
113
+ adjust_date_range(change_week, change_start, change_week.finish)
114
+ else
115
+ adjust_date_range(change_week, change_start, change_finish)
116
+ end
117
+ change_week
118
+ end
119
+
120
+ def update_and_store_week_pattern(week_pattern, args)
121
+ week_pattern.workpattern(args[:days], args[:from_time],
122
+ args[:to_time], args[:work_type])
123
+ weeks << week_pattern
124
+ end
125
+
126
+ def adjust_date_range(week_pattern, start_date, finish_date)
127
+ week_pattern.start = start_date
128
+ week_pattern.finish = finish_date
129
+ end
130
+
131
+ # Strips off hours, minutes, seconds etc from a supplied <tt>Date</tt> or
132
+ # <tt>DateTime</tt>
133
+ #
134
+ # @param [DateTime] date
135
+ # @return [DateTime] with zero hours, minutes, seconds and so forth.
136
+ #
137
+ def dmy_date(date)
138
+ Time.gm(date.year, date.month, date.day)
139
+ end
140
+
141
+ end
142
+ end
@@ -10,14 +10,15 @@ module Workpattern
10
10
  # referenced by calling applications when
11
11
  # using this gem.
12
12
  #
13
- # @since 0.2.0
14
- #
15
13
  class Workpattern
16
- include Base
17
14
 
18
15
  # Holds collection of <tt>Workpattern</tt> objects
19
16
  @@workpatterns = {}
20
17
 
18
+ def self.workpatterns
19
+ @@workpatterns
20
+ end
21
+
21
22
  # @!attribute [r] name
22
23
  # Name given to the <tt>Workpattern</tt>
23
24
  # @!attribute [r] base
@@ -33,14 +34,23 @@ module Workpattern
33
34
  #
34
35
  attr_reader :name, :base, :span, :from, :to, :weeks
35
36
 
36
- # Class for handling persistence in user's own way
37
+ # Holds local timezone info
38
+ @@tz = nil
39
+
40
+ # Converts a date like object into utc
37
41
  #
38
- def self.persistence_class=(klass)
39
- @@persist = klass
42
+ def to_utc(date)
43
+ date.to_time.utc
44
+ end
45
+ # Converts a date like object into local time
46
+ #
47
+ def to_local(date)
48
+ date.to_time.getgm
40
49
  end
41
50
 
42
- def self.persistence?
43
- @@persist ||= nil
51
+ # Retrieves the local timezone
52
+ def timezone
53
+ @@tz || @@tz = TZInfo::Timezone.get(Time.now.zone)
44
54
  end
45
55
 
46
56
  # The new <tt>Workpattern</tt> object is created with all working minutes.
@@ -51,8 +61,8 @@ module Workpattern
51
61
  # 31st December.
52
62
  # @raise [NameError] if the given name already exists
53
63
  #
54
- def initialize(name = DEFAULT_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN)
55
- if @@workpatterns.key?(name)
64
+ def initialize(name = DEFAULT_WORKPATTERN_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN)
65
+ if workpatterns.key?(name)
56
66
  raise(NameError, "Workpattern '#{name}' already exists and can't be created again")
57
67
  end
58
68
  offset = span < 0 ? span.abs - 1 : 0
@@ -60,25 +70,35 @@ module Workpattern
60
70
  @name = name
61
71
  @base = base
62
72
  @span = span
63
- @from = Time.gm(base.abs - offset)
64
- @to = Time.gm(from.year + span.abs - 1, 12, 31, 23, 59)
73
+ @from = Time.gm(@base.abs - offset)
74
+ @to = Time.gm(@from.year + @span.abs - 1, 12, 31, 23, 59)
65
75
  @weeks = SortedSet.new
66
- @weeks << Week.new(from, to, 1)
76
+ @weeks << Week.new(@from, @to)
67
77
 
68
- @@workpatterns[name] = self
78
+ workpatterns[@name] = self
79
+ @week_pattern = WeekPattern.new(self)
69
80
  end
70
81
 
82
+ def week_pattern
83
+ @week_pattern
84
+ end
85
+
86
+ private def workpatterns
87
+ @@workpatterns
88
+ end
89
+ public
90
+
71
91
  # Deletes all <tt>Workpattern</tt> objects
72
92
  #
73
93
  def self.clear
74
- @@workpatterns.clear
94
+ workpatterns.clear
75
95
  end
76
96
 
77
97
  # Returns an Array containing all the <tt>Workpattern</tt> objects
78
98
  # @return [Array] all <tt>Workpattern</tt> objects
79
99
  #
80
100
  def self.to_a
81
- @@workpatterns.to_a
101
+ workpatterns.to_a
82
102
  end
83
103
 
84
104
  # Returns the specific named <tt>Workpattern</tt>
@@ -87,7 +107,7 @@ module Workpattern
87
107
  # exist
88
108
  #
89
109
  def self.get(name)
90
- return @@workpatterns[name] if @@workpatterns.key?(name)
110
+ return workpatterns[name] if workpatterns.key?(name)
91
111
  raise(NameError, "Workpattern '#{name}' doesn't exist so can't be retrieved")
92
112
  end
93
113
 
@@ -97,7 +117,7 @@ module Workpattern
97
117
  # if it doesn't
98
118
  #
99
119
  def self.delete(name)
100
- @@workpatterns.delete(name).nil? ? false : true
120
+ workpatterns.delete(name).nil? ? false : true
101
121
  end
102
122
 
103
123
  # Applys a working or resting pattern to the <tt>Workpattern</tt> object.
@@ -116,59 +136,13 @@ module Workpattern
116
136
  # days to apply the pattern. Defaults to <tt>00:00</tt>.
117
137
  # @option opts [(#hour, #min)] :finish_time The last time in the selected
118
138
  # days to apply the pattern. Defaults to <tt>23:59</tt>.
119
- # @option opts [(WORK || REST)] :work_type Either working or resting.
139
+ # @option opts [(WORK_TYPE || REST_TYPE)] :work_type Either working or resting.
120
140
  # Defaults to working.
121
141
  # @see #working
122
142
  # @see #resting
123
143
  #
124
144
  def workpattern(opts = {})
125
- args = { start: from, finish: to, days: :all,
126
- from_time: FIRST_TIME_IN_DAY, to_time: LAST_TIME_IN_DAY,
127
- work_type: WORK }
128
-
129
- args.merge! opts
130
-
131
- @@persist.store(name: name, workpattern: args) if self.class.persistence?
132
-
133
- args[:start] = dmy_date(args[:start])
134
- args[:finish] = dmy_date(args[:finish])
135
- args[:from_time] = hhmn_date(args[:from_time])
136
- args[:to_time] = hhmn_date(args[:to_time])
137
-
138
- upd_start = to_utc(args[:start])
139
- upd_finish = to_utc(args[:finish])
140
- while upd_start <= upd_finish
141
-
142
- current_wp = find_weekpattern(upd_start)
143
-
144
- if current_wp.start == upd_start
145
- if current_wp.finish > upd_finish
146
- clone_wp = clone_and_adjust_current_wp(current_wp,
147
- upd_finish + DAY,
148
- current_wp.finish,
149
- upd_start,
150
- upd_finish)
151
- set_workpattern_and_store(clone_wp, args)
152
- upd_start = upd_finish + DAY
153
- else # (current_wp.finish == upd_finish)
154
- current_wp.workpattern(args[:days], args[:from_time],
155
- args[:to_time], args[:work_type])
156
- upd_start = current_wp.finish + DAY
157
- end
158
- else
159
- clone_wp = clone_and_adjust_current_wp(current_wp, current_wp.start,
160
- upd_start - DAY, upd_start)
161
- if clone_wp.finish > upd_finish
162
- after_wp = clone_and_adjust_current_wp(clone_wp,
163
- upd_start,
164
- upd_finish,
165
- upd_finish + DAY)
166
- weeks << after_wp
167
- end
168
- set_workpattern_and_store(clone_wp, args)
169
- upd_start = clone_wp.finish + DAY
170
- end
171
- end
145
+ week_pattern.workpattern(opts)
172
146
  end
173
147
 
174
148
  # Convenience method that calls <tt>#workpattern</tt> with the
@@ -177,7 +151,7 @@ module Workpattern
177
151
  # @see #workpattern
178
152
  #
179
153
  def resting(args = {})
180
- args[:work_type] = REST
154
+ args[:work_type] = REST_TYPE
181
155
  workpattern(args)
182
156
  end
183
157
 
@@ -187,10 +161,67 @@ module Workpattern
187
161
  # @see #workpattern
188
162
  #
189
163
  def working(args = {})
190
- args[:work_type] = WORK
164
+ args[:work_type] = WORK_TYPE
191
165
  workpattern(args)
192
166
  end
193
167
 
168
+ def to_h
169
+ { version: 1,
170
+ name: @name,
171
+ base: @base,
172
+ span: @span,
173
+ weeks: @weeks.map(&:to_h) }
174
+ end
175
+
176
+ def self.from_h(hash, overwrite: false)
177
+ unless hash.key?(:version)
178
+ raise ArgumentError, "from_h: hash is missing a :version key " \
179
+ "(if deserialising from JSON, use symbolize_names: true)"
180
+ end
181
+ unless hash[:version] == 1
182
+ raise ArgumentError, "from_h: unsupported version #{hash[:version].inspect} " \
183
+ "(supported: 1)"
184
+ end
185
+ unless hash[:name].is_a?(String) && !hash[:name].empty?
186
+ raise ArgumentError, "from_h: :name must be a non-empty String"
187
+ end
188
+ unless hash[:base].is_a?(Integer)
189
+ raise ArgumentError, "from_h: :base must be an Integer"
190
+ end
191
+ unless hash[:span].is_a?(Integer) && hash[:span] != 0
192
+ raise ArgumentError, "from_h: :span must be a non-zero Integer"
193
+ end
194
+ unless hash[:weeks].is_a?(Array)
195
+ raise ArgumentError, "from_h: :weeks must be an Array"
196
+ end
197
+
198
+ name = hash[:name]
199
+ if workpatterns.key?(name) && !overwrite
200
+ raise NameError, "Workpattern '#{name}' already exists and can't be created again"
201
+ end
202
+
203
+ wp = allocate
204
+ wp.instance_variable_set(:@name, name)
205
+ wp.instance_variable_set(:@base, hash[:base])
206
+ wp.instance_variable_set(:@span, hash[:span])
207
+
208
+ offset = hash[:span] < 0 ? hash[:span].abs - 1 : 0
209
+ from_time = Time.gm(hash[:base].abs - offset)
210
+ to_time = Time.gm(from_time.year + hash[:span].abs - 1, 12, 31, 23, 59)
211
+ wp.instance_variable_set(:@from, from_time)
212
+ wp.instance_variable_set(:@to, to_time)
213
+
214
+ weeks = SortedSet.new
215
+ hash[:weeks].each { |wh| weeks << Week.from_h(wh) }
216
+ raise ArgumentError, "from_h: :weeks must not be empty" if weeks.empty?
217
+ wp.instance_variable_set(:@weeks, weeks)
218
+ wp.instance_variable_set(:@week_pattern, WeekPattern.new(wp))
219
+
220
+ workpatterns.delete(name) if overwrite
221
+ workpatterns[name] = wp
222
+ wp
223
+ end
224
+
194
225
  # Calculates the resulting date when the <tt>duration</tt> in minutes
195
226
  # is added to the <tt>start</tt> date.
196
227
  # The <tt>duration</tt> is always in whole minutes and subtracts from
@@ -203,20 +234,26 @@ module Workpattern
203
234
  #
204
235
  def calc(start, duration)
205
236
  return start if duration == 0
206
- midnight = false
237
+ a_day = SAME_DAY
207
238
 
208
239
  utc_start = to_utc(start)
240
+
209
241
  while duration != 0
210
- week = find_weekpattern(utc_start)
211
- if (week.start == utc_start) && (duration < 0) && !midnight
212
- utc_start = utc_start.prev_day
213
- week = find_weekpattern(utc_start)
214
- midnight = true
215
- end
216
242
 
217
- utc_start, duration, midnight = week.calc(utc_start, duration, midnight)
243
+ if a_day == PREVIOUS_DAY
244
+ utc_start -= DAY
245
+ a_day = SAME_DAY
246
+ utc_start = Time.gm(utc_start.year, utc_start.month, utc_start.day,LAST_TIME_IN_DAY.hour, LAST_TIME_IN_DAY.min)
247
+ week = find_weekpattern(utc_start)
248
+
249
+ if week.working?(utc_start)
250
+ duration += 1
251
+ end
252
+ else
253
+ week = find_weekpattern(utc_start)
254
+ end
255
+ utc_start, duration, a_day = week.calc(utc_start, duration, a_day)
218
256
  end
219
-
220
257
  to_local(utc_start)
221
258
  end
222
259
 
@@ -239,18 +276,17 @@ module Workpattern
239
276
  def diff(start, finish)
240
277
  utc_start = to_utc(start)
241
278
  utc_finish = to_utc(finish)
242
- utc_start, utc_finish = utc_finish, utc_start if finish < start
243
- duration = 0
279
+ utc_start, utc_finish = utc_finish, utc_start if utc_finish < utc_start
280
+ minutes = 0
281
+
244
282
  while utc_start != utc_finish
245
283
  week = find_weekpattern(utc_start)
246
- result_duration, utc_start = week.diff(utc_start, utc_finish)
247
- duration += result_duration
284
+ r_minutes, utc_start = week.diff(utc_start, utc_finish)
285
+ minutes += r_minutes
248
286
  end
249
- duration
287
+ minutes
250
288
  end
251
289
 
252
- private
253
-
254
290
  # Retrieve the correct <tt>Week</tt> pattern for the supplied date.
255
291
  #
256
292
  # If the supplied <tt>date</tt> is outside the span of the
@@ -264,61 +300,17 @@ module Workpattern
264
300
  def find_weekpattern(date)
265
301
  # find the pattern that fits the date
266
302
  #
267
- if date < from
268
- result = Week.new(Time.at(0), from - MINUTE, 1)
303
+ if date < @from
304
+ result = Week.new(Time.at(0), @from - MINUTE, WORK_TYPE)
269
305
  elsif date > to
270
- result = Week.new(to + MINUTE, Time.new(9999), 1)
306
+ result = Week.new(@to + MINUTE, Time.new(9999), WORK_TYPE)
271
307
  else
272
308
 
273
309
  date = Time.gm(date.year, date.month, date.day)
274
310
 
275
- result = weeks.find { |week| week.start <= date && week.finish >= date }
311
+ result = @weeks.find { |week| week.start <= date && week.finish >= date }
276
312
  end
277
313
  result
278
314
  end
279
-
280
- # Strips off hours, minutes, seconds etc from a supplied <tt>Date</tt> or
281
- # <tt>DateTime</tt>
282
- #
283
- # @param [DateTime] date
284
- # @return [DateTime] with zero hours, minutes, seconds and so forth.
285
- #
286
- def dmy_date(date)
287
- Time.gm(date.year, date.month, date.day)
288
- end
289
-
290
- # Extract the time into a <tt>Clock</tt> object
291
- #
292
- # @param [DateTime] date
293
- # @return [Clock]
294
- def hhmn_date(date)
295
- Clock.new(date.hour, date.min)
296
- end
297
-
298
- # Handles cloning of Week Pattern including date adjustments
299
- #
300
- def clone_and_adjust_current_wp(current_wp, current_start, current_finish,
301
- clone_start, clone_finish = nil)
302
- clone_wp = current_wp.duplicate
303
- adjust_date_range(current_wp, current_start, current_finish)
304
- if clone_finish.nil?
305
- adjust_date_range(clone_wp, clone_start, clone_wp.finish)
306
- else
307
- adjust_date_range(clone_wp, clone_start, clone_finish)
308
- end
309
- clone_wp
310
- end
311
-
312
- def set_workpattern_and_store(new_wp, args)
313
- new_wp.workpattern(args[:days], args[:from_time],
314
- args[:to_time], args[:work_type])
315
- weeks << new_wp
316
- end
317
-
318
- def adjust_date_range(week_pattern, start_date, finish_date)
319
- week_pattern.start = start_date
320
- week_pattern.finish = finish_date
321
- end
322
-
323
315
  end
324
316
  end
data/lib/workpattern.rb CHANGED
@@ -7,12 +7,14 @@ $LOAD_PATH.unshift(File.dirname(__FILE__)) unless
7
7
  $LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
8
8
 
9
9
  require 'rubygems'
10
+ require 'sorted_set' if RUBY_VERSION >= "2.4"
10
11
  require 'date'
11
- require 'workpattern/utility/base.rb'
12
12
  require 'workpattern/clock'
13
- #require 'workpattern/day'
13
+ require 'workpattern/constants'
14
+ require 'workpattern/day'
14
15
  require 'workpattern/week'
15
16
  require 'workpattern/workpattern'
17
+ require 'workpattern/week_pattern'
16
18
 
17
19
  #
18
20
  # workpattern.rb - date calculation library that takes into account patterns of
@@ -24,67 +26,7 @@ require 'workpattern/workpattern'
24
26
  # Documentation: Barrie Callender <barrie@callenb.org>
25
27
  #
26
28
  module Workpattern
27
- # Represents a full working hour
28
- # @since 0.2.0
29
- WORKING_HOUR = 2**60 - 1
30
29
 
31
- # Represents a full resting hour
32
- # @since 0.2.0
33
- RESTING_HOUR = 0
34
-
35
- # The default workpattern name
36
- # @since 0.2.0
37
- DEFAULT_WORKPATTERN_NAME = 'default'.freeze
38
-
39
- # The default base year
40
- # @since 0.2.0
41
- DEFAULT_BASE_YEAR = 2000
42
-
43
- # The default span in years
44
- # @since 0.2.0
45
- DEFAULT_SPAN = 100
46
-
47
- # Minute in terms of seconds
48
- #
49
- MINUTE = 60
50
-
51
- # Hour interms od seconds
52
- #
53
- HOUR = MINUTE * 60
54
-
55
- # Day in terms of seconds
56
- #
57
- DAY = HOUR * 24
58
-
59
- # Earliest or first time in the day
60
- # @since 0.0.1
61
- FIRST_TIME_IN_DAY = Clock.new(0, 0)
62
-
63
- # Latest or last time in the day
64
- # @since 0.0.1
65
- LAST_TIME_IN_DAY = Clock.new(23, 59)
66
-
67
- # Specifies a working pattern
68
- # @since 0.0.1
69
- WORK = 1
70
-
71
- # Specifies a resting pattern
72
- # @since 0.0.1
73
- REST = 0
74
-
75
- # Represents the days of the week to be used in applying working
76
- # and resting patterns.
77
- # Values exist for each day of the week as well as for the weekend
78
- # (Saturday and Sunday),
79
- # the week (Monday to Friday) and all days in the week.
80
- #
81
- # @since 0.0.1
82
- daynames = { sun: [0], mon: [1], tue: [2], wed: [3],
83
- thu: [4], fri: [5], sat: [6],
84
- weekday: [1, 2, 3, 4, 5],
85
- weekend: [0, 6],
86
- all: [0, 1, 2, 3, 4, 5, 6] }
87
- DAYNAMES = daynames.freeze
88
30
  # Covenience method to obtain a new <tt>Workpattern</tt>
89
31
  #
90
32
  # A negative <tt>span</tt> counts back from the <tt>base</tt> year
@@ -94,7 +36,6 @@ module Workpattern
94
36
  # @param [Integer] number of years ending on 31st December.
95
37
  # @return [Workpattern]
96
38
  # @raise [NameError] creating a Workpattern with a name that already exists
97
- # @since 0.2.0
98
39
  #
99
40
  def self.new(name = DEFAULT_WORKPATTERN_NAME,
100
41
  base = DEFAULT_BASE_YEAR,
@@ -107,8 +48,6 @@ module Workpattern
107
48
  #
108
49
  # @return [Array] all <tt>Workpattern</tt> objects
109
50
  #
110
- # @since 0.2.0
111
- #
112
51
  def self.to_a
113
52
  Workpattern.to_a
114
53
  end
@@ -118,8 +57,6 @@ module Workpattern
118
57
  # @param [String] name The name of the Workpattern to retrieve.
119
58
  # @return [Workpattern]
120
59
  #
121
- # @since 0.2.0
122
- #
123
60
  def self.get(name)
124
61
  Workpattern.get(name)
125
62
  end
@@ -128,20 +65,36 @@ module Workpattern
128
65
  #
129
66
  # @param [String] name The name of the Workpattern to be deleted.
130
67
  #
131
- # @since 0.2.0
132
- #
133
68
  def self.delete(name)
134
69
  Workpattern.delete(name)
135
70
  end
136
71
 
137
72
  # Convenience method to delete all Workpatterns.
138
73
  #
139
- # @since 0.2.0
140
- #
141
74
  def self.clear
142
75
  Workpattern.clear
143
76
  end
144
77
 
78
+ # Convenience method to deserialise a Workpattern from a plain hash.
79
+ #
80
+ # @param [Hash] hash produced by Workpattern#to_h
81
+ # @param [Boolean] overwrite replace an existing same-named workpattern
82
+ # @return [Workpattern]
83
+ # @raise [ArgumentError] if the hash is missing or has an unsupported version
84
+ # @raise [NameError] if a same-named workpattern already exists and overwrite is false
85
+ #
86
+ def self.from_h(hash, overwrite: false)
87
+ Workpattern.from_h(hash, overwrite: overwrite)
88
+ end
89
+
90
+ # Convenience method to access the registry of all known Workpattern objects.
91
+ #
92
+ # @return [Hash]
93
+ #
94
+ def self.workpatterns
95
+ Workpattern.workpatterns
96
+ end
97
+
145
98
  # Convenience method to create a Clock object. This can be used for
146
99
  # specifying times if you don't want to create a <tt>DateTime</tt> object
147
100
  #
@@ -150,9 +103,8 @@ module Workpattern
150
103
  # @return [Clock]
151
104
  # @see Clock
152
105
  #
153
- # @since 0.2.0
154
- #
155
106
  def self.clock(hour, min)
156
107
  Clock.new(hour, min)
157
108
  end
109
+
158
110
  end
data/script/console CHANGED
File without changes
data/script/destroy CHANGED
File without changes
data/script/generate CHANGED
File without changes
data/script/txt2html CHANGED
File without changes