Class: Workpattern::Workpattern

Inherits:
Object
  • Object
show all
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 Workpattern objects

{}
@@tz =

Holds local timezone info

nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = DEFAULT_NAME, base = DEFAULT_BASE_YEAR, span = DEFAULT_SPAN) ⇒ Workpattern

The new Workpattern object is created with all working minutes.

31st December.

Parameters:

  • name (String) (defaults to: DEFAULT_NAME)

    Every workpattern has a unique name

  • base (Integer) (defaults to: DEFAULT_BASE_YEAR)

    Workpattern starts on the 1st January of this year.

  • span (Integer) (defaults to: DEFAULT_SPAN)

    Workpattern spans this number of years ending on

Raises:

  • (NameError)

    if the given name already exists



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/workpattern/workpattern.rb', line 78

def initialize(name = DEFAULT_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

#baseObject (readonly)

Starting year



39
# File 'lib/workpattern/workpattern.rb', line 39

attr_reader :name, :base, :span, :from, :to, :weeks

#fromObject (readonly)

First date in Workpattern



39
# File 'lib/workpattern/workpattern.rb', line 39

attr_reader :name, :base, :span, :from, :to, :weeks

#nameObject (readonly)

Name given to the Workpattern



39
40
41
# File 'lib/workpattern/workpattern.rb', line 39

def name
  @name
end

#spanObject (readonly)

Number of years



39
# File 'lib/workpattern/workpattern.rb', line 39

attr_reader :name, :base, :span, :from, :to, :weeks

#toObject (readonly)

Last date in Workpattern



39
# File 'lib/workpattern/workpattern.rb', line 39

attr_reader :name, :base, :span, :from, :to, :weeks

#weeksObject (readonly)

Returns the value of attribute weeks.



39
# File 'lib/workpattern/workpattern.rb', line 39

attr_reader :name, :base, :span, :from, :to, :weeks

Class Method Details

.clearObject

Deletes all Workpattern objects



102
103
104
# File 'lib/workpattern/workpattern.rb', line 102

def self.clear
  workpatterns.clear
end

.delete(name) ⇒ Boolean

Deletes the specific named Workpattern if it doesn’t

Parameters:

  • name (String)

    of the required Workpattern

Returns:

  • (Boolean)

    true if the named Workpattern existed or false



128
129
130
# File 'lib/workpattern/workpattern.rb', line 128

def self.delete(name)
  workpatterns.delete(name).nil? ? false : true
end

.get(name) ⇒ Object

Returns the specific named Workpattern exist

Parameters:

  • name (String)

    of the required Workpattern

Raises:

  • (NameError)

    if a Workpattern of the supplied name does not



118
119
120
121
# File 'lib/workpattern/workpattern.rb', line 118

def self.get(name)
  return workpatterns[name] if workpatterns.key?(name)
  raise(NameError, "Workpattern '#{name}' doesn't exist so can't be retrieved")
end

.persistence?Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/workpattern/workpattern.rb', line 47

def self.persistence?
  @@persist ||= nil
end

.persistence_class=(klass) ⇒ Object

Class for handling persistence in user’s own way



43
44
45
# File 'lib/workpattern/workpattern.rb', line 43

def self.persistence_class=(klass)
  @@persist = klass
end

.to_aArray

Returns an Array containing all the Workpattern objects

Returns:

  • (Array)

    all Workpattern objects



109
110
111
# File 'lib/workpattern/workpattern.rb', line 109

def self.to_a
  workpatterns.to_a
end

.workpatternsObject



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

Parameters:

  • start (DateTime)

    date to add or subtract minutes

  • duration (Integer)

    in minutes to add or subtract to date

Returns:

  • (DateTime)

    the date when duration is added to



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/workpattern/workpattern.rb', line 191

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

Parameters:

  • start (DateTime)

    is the date to start from

  • finish (DateTime)

    is the date to end with

Returns:

  • (Integer)

    number of minutes between the two dates



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/workpattern/workpattern.rb', line 232

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

Parameters:

  • date (DateTime)

    whose containing Week pattern is required

Returns:

  • (Week)

    Week object that includes the supplied



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/workpattern/workpattern.rb', line 256

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.

See Also:



166
167
168
169
# File 'lib/workpattern/workpattern.rb', line 166

def resting(args = {})
  args[:work_type] = REST_TYPE
  workpattern(args)
end

#timezoneObject

Retrieves the local timezone



66
67
68
# File 'lib/workpattern/workpattern.rb', line 66

def timezone
  @@tz || @@tz = TZInfo::Timezone.get(Time.now.zone)
end

#to_local(date) ⇒ Object

Converts a date like object into local time



61
62
63
# File 'lib/workpattern/workpattern.rb', line 61

def to_local(date)
  date.to_time.getgm
end

#to_utc(date) ⇒ Object

Converts a date like object into utc



56
57
58
# File 'lib/workpattern/workpattern.rb', line 56

def to_utc(date)
  date.to_time.utc
end

#week_patternObject



96
97
98
# File 'lib/workpattern/workpattern.rb', line 96

def week_pattern
  @week_pattern
end

#working(args = {}) ⇒ Object

Convenience method that calls #workpattern with the :work_type specified as working.

See Also:



176
177
178
179
# File 'lib/workpattern/workpattern.rb', line 176

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.

Parameters:

  • start (DateTime)

    DateTime being tested

Returns:

  • (Boolean)

    true if working and false if resting



221
222
223
224
# File 'lib/workpattern/workpattern.rb', line 221

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.

Parameters:

  • opts (Hash) (defaults to: {})

    the options used to apply a workpattern

Options Hash (opts):

  • :start (Date)

    The first date to apply the pattern. Defaults to the start attribute.

  • :finish (Date)

    The last date to apply the pattern. Defaults to the finish attribute.

  • :days (DAYNAMES)

    The specific day or days the pattern will

  • :start_time ((#hour, #min))

    The first time in the selected

  • :finish_time ((#hour, #min))

    The last time in the selected

  • :work_type ((WORK_TYPE || REST_TYPE))

    Either working or resting.

See Also:



153
154
155
156
157
158
159
# File 'lib/workpattern/workpattern.rb', line 153

def workpattern(opts = {})
  if self.class.persistence?
    week_pattern.workpattern(opts, @@persistence)
  else
    week_pattern.workpattern(opts)
  end
end

#workpatternsObject



22
23
24
# File 'lib/workpattern/workpattern.rb', line 22

def workpatterns
  @@workpatterns
end