workpattern 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ ## Workpattern v0.3.1 (Oct 14, 2012) ##
2
+
3
+ * RDOC documentation not right on rubydoc.info (#5) * Barrie Callender *
4
+
1
5
  ## Workpattern v0.3.0 (Jul 19, 2012) ##
2
6
 
3
7
  * incomplete tests for week (#2) * Barrie Callender *
data/README.md CHANGED
@@ -4,6 +4,25 @@
4
4
 
5
5
  Simple addition and subtraction of minutes on dates taking account of real-life working and resting periods.
6
6
 
7
+ ## So What?
8
+
9
+ The core Ruby classes that represent date and time allow calculations by adding a duration such as days or
10
+ minutes to a date and returning the new `Date` or `DateTime` as the result. Although there
11
+ are 60 seconds in every minute and 60 minutes in every hour, there aren't always 24 hours in every day, and
12
+ if there was, we still wouldn't be working during all of them. We would be doing other things like eating,
13
+ sleeping, travelling and having a bit of leisure time. Workpattern refers to this time as Resting time.
14
+ It refers to the time when we're busy doing stuff as Working time.
15
+
16
+ When it comes to scheduling work, whether part of a project, teachers in a classroom or even bed availability
17
+ in a hospital, the working day can have anything from 0 hours to the full 24 hours. Most office based work
18
+ is something like 7.5 or 8 hours a day except weekends, public holidays and vacations when no work takes
19
+ place.
20
+
21
+ The `Workpattern` library was born to allow date related calculations to take into account real life
22
+ working and resting times. It gets told about working and resting periods and can then perform calculations
23
+ on a given date. It can add and subtract a number of minutes, calculate the working minutes between two dates
24
+ and say whether a specific minute is working or resting.
25
+
7
26
  This gem has the potential to serve as the engine for scheduling algorithms that are the core of products such as Microsoft Project and Oracle Primavera P6 as well as other applications that need to know when they can perform work and when they can’t.
8
27
 
9
28
  ## Install
@@ -12,19 +31,19 @@ This gem has the potential to serve as the engine for scheduling algorithms that
12
31
 
13
32
  ## Getting Started
14
33
 
15
- The first step is to create a **Workpattern** to hold all the working and resting times. I'll start in 2011 and let it run for 10 years.
34
+ The first step is to create a `Workpattern` to hold all the working and resting times. I'll start in 2011 and let it run for 10 years.
16
35
 
17
36
  ``` ruby
18
37
  mywp=Workpattern.new('My Workpattern',2011,10)
19
38
  ```
20
39
 
21
- My **Workpattern** will be created as a 24 hour a day full working time. Now it has to be told about the resting periods. First the weekends.
40
+ My `Workpattern` will be created as a 24 hour a day full working time. Now it has to be told about the resting periods. First the weekends.
22
41
 
23
42
  ``` ruby
24
43
  mywp.resting(:days => :weekend)
25
44
  ```
26
45
 
27
- then the days in the week have specific working and resting times using the *Workpattern.clock* method, although anything that responds to **hour** and **min** methods will do ...
46
+ then the days in the week have specific working and resting times using the *Workpattern.clock* method, although anything that responds to `#hour` and `#min` methods will do ...
28
47
 
29
48
  ``` ruby
30
49
  mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(0,0),:to_time=>Workpattern.clock(8,59))
@@ -47,6 +66,32 @@ result_date = mywp.calc(mydate,1920) # => 6/9/11@18:00
47
66
  * Pull requests are very welcome, however I have never participated in Open Source so will be a bit slow as I am learning. Please be patient with me. Please include spec and/or feature coverage for every patch, and create a topic branch for every separate change you make.
48
67
  * Advice, such as pointing out how I should really code in Ruby will be gratefully received.
49
68
 
69
+ ## Things To Do
70
+
71
+ In its current form this library is being made available to see if there is any interest in using
72
+ it. At the moment it can perform the following:
73
+
74
+ * define the working and resting minutes for any 24 hour day
75
+ * given a date it can return the resulting date after adding or subtracting a number of minutes
76
+ * calculate the number of working minutes between two dates
77
+ * report whether a specific minute in time is working or resting
78
+
79
+ This is what I consider to be the basics, but there are a number of functional and non-functial areas I
80
+ would like to address in a future version.
81
+
82
+ ## Functional
83
+
84
+ * Merge two Workpatterns together to create a new one allowing either resting or working to take precedence
85
+ * Given a date, find the next working or resting minute either before or after it.
86
+ * Handle both 23 and 25 hour days that occur when the clocks change.
87
+ * Extract patterns from the workpattern so they can be persisted in a database.
88
+ * Decide how to handle different Timezones apart from UTC.
89
+
90
+ ## Non-Functional
91
+
92
+ * Improve the documentation and introduce real world use as an example
93
+ * Improve my ability to write Ruby code
94
+
50
95
  ## License
51
96
 
52
97
  (The MIT License)
data/lib/workpattern.rb CHANGED
@@ -24,202 +24,126 @@ require 'workpattern/workpattern'
24
24
  #
25
25
  # Documentation: Barrie Callender <barrie@callenb.org>
26
26
  #
27
- # == Overview
28
- #
29
- # The core Ruby classes that represent date and time allow calculations by
30
- # adding a duration such as days or minutes to a date and returning the new
31
- # <tt>Date</tt> or <tt>DateTime</tt> as the result.
32
- #
33
- # Although there are 60 seconds in every minute and 60 minutes in every hour, there
34
- # aren't always 24 hours in every day, and if there was, we still wouldn't
35
- # be working during all of them. We would be doing other things like eating,
36
- # sleeping, travelling and having a bit of leisure time. Workpattern refers to this
37
- # time as Resting time. It refers to the time when we're busy doing stuff as
38
- # Working time.
39
- #
40
- # When it comes to scheduling work, whether part of a project, teachers in a
41
- # classroom or even bed availability in a hospital, the working day can have
42
- # anything from 0 hours to the full 24 hours. Most office based work
43
- # is something like 7.5 or 8 hours a day except weekends, public holidays and
44
- # vacations when no work takes place.
45
- #
46
- # The <tt>Workpattern</tt> library was born to allow date related calculations to take
47
- # into account real life working and resting times. It gets told about working
48
- # and resting periods and can then perform calculations on a given date. It can
49
- # add and subtract a number of minutes, calculate the working minutes between
50
- # two dates and say whether a specific minute is working or resting.
51
- #
52
- # == Illustration
53
- #
54
- # In real life we may be reasonably confident that it will take us 32 hours to
55
- # write a document. If we started on a Thursday at 9:00am we wouldn't be
56
- # working 32 hours without interruption (let's pretend we're not software
57
- # developers for this one!). We'd go home at the end of one working day and
58
- # not return until the next. The weekend would not include working on the
59
- # document either. We would probably work 8 hours on Thursday, Friday, Monday
60
- # and Tuesday to complete the work.
61
- #
62
- # The <tt>Workpattern</tt> library will be able to tell you that if you started at
63
- # 9:00 am on Thursday, you should be finished at 6:00 pm on Tuesday - allowing an hour
64
- # for lunch each day! For it to do that it has to know when you can work and
65
- # when you are resting.
66
- #
67
- # == An Example Session
68
- #
69
- # Using the illustration as a basis, we want to find out when I will finish the document.
70
- # It is going to take me 32 hours to complete the document and I'm going to start on it
71
- # as soon as I arrive at work on the morning of Thursday 1st September 2011. My working
72
- # day starts at 9:00am,finishes at 6:00pm and I take an hour for lunch. I don't work
73
- # on the weekend.
74
- #
75
- # The first step is to create a <tt>Workpattern</tt> to hold all the working and resting times.
76
- # I'll start in 2011 and let it run for 10 years.
77
- #
78
- # mywp=Workpattern.new('My Workpattern',2011,10)
79
- #
80
- # My <tt>Workpattern</tt> will be created as a 24 hour a day full working time. Now it has to
81
- # be told about the resting periods. First the weekends.
82
- #
83
- # mywp.resting(:days => :weekend)
84
- #
85
- # then the days in the week have specific working and resting times using the
86
- # <tt>Time::hm</tt> method added by <tt>Workpattern</tt> ...
87
- #
88
- # mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(0,0),:to_time=>Workpattern.clock(8,59))
89
- # mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(12,0),:to_time=>Workpattern.clock(12,59))
90
- # mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(18,0),:to_time=>Workpattern.clock(23,59))
91
- #
92
- # Now we have the working and resting periods setup we can just add 32 hours as
93
- # minutes (1920) to our date.
94
- #
95
- # mydate=DateTime.civil(2011,9,1,9,0)
96
- # result_date = mywp.calc(mydate,1920) # => 6/9/11@18:00
97
- #
98
- # == Things To Do
99
- #
100
- # In its current form this library is being made available to see if there is any interest
101
- # in using it. At the moment it can perform the following:
102
- # * define the working and resting minutes for any 24 hour day
103
- # * given a date it can return the resulting date after adding or subtracting a number of minutes
104
- # * calculate the number of working minutes between two dates
105
- # * report whether a specific minute in time is working or resting
106
- # This is what I consider to be the basics, but there are a number of functional and
107
- # non-functial areas I would like to address in a future version.
108
- #
109
- # === Functional
110
- #
111
- # * Merge two Workpatterns together to create a new one allowing either resting or working to take precedence
112
- # * Given a date, find the next working or resting minute either before or after it.
113
- # * Handle both 23 and 25 hour days that occur when the clocks change.
114
- # * Extract patterns from the workpattern so they can be persisted in a database.
115
- # * Decide how to handle different Timezones apart from UTC.
116
- #
117
- # === Non-Functional
118
- #
119
- # * Improve the documentation and introduce real world use as an example
120
- # * Improve my ability to write Ruby code
121
- #
122
27
  module Workpattern
123
28
 
124
29
  # Represents a full working hour
30
+ # @since 0.2.0
125
31
  WORKING_HOUR = 2**60-1
32
+
126
33
  # Represents a full resting hour
34
+ # @since 0.2.0
127
35
  RESTING_HOUR = 0
36
+
128
37
  # The default workpattern name
38
+ # @since 0.2.0
129
39
  DEFAULT_WORKPATTERN_NAME = 'default'
40
+
130
41
  # The default base year
42
+ # @since 0.2.0
131
43
  DEFAULT_BASE_YEAR = 2000
44
+
132
45
  # The default span in years
46
+ # @since 0.2.0
133
47
  DEFAULT_SPAN = 100
48
+
134
49
  # Hour in terms of days
50
+ # @since 0.2.0
135
51
  HOUR = Rational(1,24)
52
+
136
53
  # Minute in terms of days
54
+ # @since 0.2.0
137
55
  MINUTE = Rational(1,1440)
138
- # earliest or first time in the day
56
+
57
+ # Earliest or first time in the day
58
+ # @since 0.0.1
139
59
  FIRST_TIME_IN_DAY=Clock.new(0,0)
140
- # latest or last time in the day
60
+
61
+ # Latest or last time in the day
62
+ # @since 0.0.1
141
63
  LAST_TIME_IN_DAY=Clock.new(23,59)
142
- # specifies a working pattern
64
+
65
+ # Specifies a working pattern
66
+ # @since 0.0.1
143
67
  WORK = 1
144
- # specifies a resting pattern
68
+
69
+ # Specifies a resting pattern
70
+ # @since 0.0.1
145
71
  REST = 0
72
+
146
73
  # Represents the days of the week to be used in applying working and resting patterns.
74
+ # Values exist for each day of the week as well as for the weekend (Saturday and Sunday),
75
+ # the week (Monday to Friday) and all days in the week.
147
76
  #
148
- # ==== Valid Values
149
- #
150
- # <tt>:sun, :mon, :tue, :wed, :thu, :fri, :sat</tt> a day of the week.
151
- # <tt>:all</tt> all days of the week.
152
- # <tt>:weekend</tt> Saturday and Sunday.
153
- # <tt>:weekday</tt> Monday to Friday inclusive.
154
- #
77
+ # @since 0.0.1
155
78
  DAYNAMES={:sun => [0],:mon => [1], :tue => [2], :wed => [3], :thu => [4], :fri => [5], :sat => [6],
156
79
  :weekday => [1,2,3,4,5],
157
80
  :weekend => [0,6],
158
81
  :all => [0,1,2,3,4,5,6]}
159
82
 
160
- # :call-seq: new(name, base, span) => workpattern
83
+ # Covenience method to obtain a new <tt>Workpattern</tt>
161
84
  #
162
- # Covenience method to obtain a new <tt>Workpattern::Workpattern</tt>
85
+ # A negative <tt>span</tt> counts back from the <tt>base</tt> year
163
86
  #
164
- # ==== Parameters
87
+ # @param [String] name Every workpattern has a unique name.
88
+ # @param [Integer] base Workpattern starts on the 1st January of this year.
89
+ # @param [Integer] span Workpattern spans this number of years ending on 31st December.
90
+ # @return [Workpattern]
165
91
  #
166
- # +name+::
167
- # Every workpattern has a unique name.
168
- # +base+::
169
- # The starting year for the range of dates the Calendar
170
- # can use. Always the 1st january.
171
- # +span+::
172
- # Duration of the Calendar in years. If <tt>span</tt> is negative
173
- # then the range counts backwards from the <tt>base</tt>.
92
+ # @since 0.2.0
174
93
  #
175
94
  def self.new(name=DEFAULT_WORKPATTERN_NAME, base=DEFAULT_BASE_YEAR, span=DEFAULT_SPAN)
176
95
  return Workpattern.new(name, base,span)
177
96
  end
178
97
 
179
- # :call-seq: to_a => array
98
+ # Covenience method to obtain an Array of all the known <tt>Workpattern</tt> objects
99
+ #
100
+ # @return [Array] all <tt>Workpattern</tt> objects
180
101
  #
181
- # Covenience method to obtain an Array of all the known <tt>Workpattern::Workpattern</tt> objects
102
+ # @since 0.2.0
182
103
  #
183
104
  def self.to_a()
184
105
  return Workpattern.to_a
185
106
  end
186
107
 
187
- # :call-seq: get(name) => workpattern
108
+ # Covenience method to obtain an existing <tt>Workpattern</tt>
188
109
  #
189
- # Covenience method to obtain an existing <tt>Workpattern::Workpattern</tt>
110
+ # @param [String] name The name of the Workpattern to retrieve.
111
+ # @return [Workpattern]
190
112
  #
191
- # ==== Parameters
192
- #
193
- # +name+:: The name of the Workpattern.
113
+ # @since 0.2.0
194
114
  #
195
115
  def self.get(name)
196
116
  return Workpattern.get(name)
197
117
  end
198
118
 
199
- # :call-seq: delete(name) => boolean
200
- #
201
- # Convenience method to delete the named <tt>Workpattern::Workpattern</tt>
119
+ # Convenience method to delete the named <tt>Workpattern</tt>
202
120
  #
203
- # === Parameters
121
+ # @param [String] name The name of the Workpattern to be deleted.
204
122
  #
205
- # +name+:: The name of the Workpattern.
123
+ # @since 0.2.0
206
124
  #
207
125
  def self.delete(name)
208
126
  Workpattern.delete(name)
209
127
  end
210
128
 
211
- # :call-seq: clear
212
- #
213
129
  # Convenience method to delete all Workpatterns.
214
130
  #
131
+ # @since 0.2.0
132
+ #
215
133
  def self.clear
216
134
  Workpattern.clear
217
135
  end
218
136
 
219
- # :call-seq: clock(hour,min)
220
- #
221
- # Convenience method to create a Clock object. This can be used for specifying times.
137
+ # Convenience method to create a Clock object. This can be used for specifying times
138
+ # if you don't want to create a <tt>DateTime</tt> object
222
139
  #
140
+ # @param [Integer] hour the number of hours.
141
+ # @param [Integer] min the number of minutes
142
+ # @return [Clock]
143
+ # @see Clock
144
+ #
145
+ # @since 0.2.0
146
+ #
223
147
  def self.clock(hour,min)
224
148
  return Clock.new(hour,min)
225
149
  end
@@ -1,27 +1,33 @@
1
1
  module Workpattern
2
2
  # Represents time on a clock in hours and minutes.
3
3
  #
4
- # myClock=Clock.new(3,32)
5
- # myClock.minutes #=> 212
6
- # myClock.hour #=> 3
7
- # myClock.min #=> 32
8
- # myClock.time #=> Time.new(1963,6,10,3,32)
9
- #
4
+ # @example
5
+ # myClock=Clock.new(3,32)
6
+ # myClock.minutes #=> 212
7
+ # myClock.hour #=> 3
8
+ # myClock.min #=> 32
9
+ # myClock.time #=> Time.new(1963,6,10,3,32)
10
+ # myClock.to_s #=> 3:32 212
10
11
  #
11
- # aClock=Clock.new(27,80)
12
- # aClock.minutes #=> 1700
13
- # aClock.hour #=> 4
14
- # aClock.min #=> 20
15
- # aClock.time #=> Time.new(1963,6,10,4,20)
12
+ # aClock=Clock.new(27,80)
13
+ # aClock.minutes #=> 1700
14
+ # aClock.hour #=> 4
15
+ # aClock.min #=> 20
16
+ # aClock.time #=> Time.new(1963,6,10,4,20)
17
+ # aClock.to_s #=> 4:20 1700
18
+ #
19
+ # @since 0.2.0
16
20
  #
17
21
  class Clock
18
-
19
- # :call-seq: new(hour,min) => Clock
20
- # initialises <tt>Clock</tt> using the hours and minutes supplied
22
+
23
+ # Initialises an instance of <tt>Clock</tt> using the hours and minutes supplied
21
24
  # or 0 if they are absent. Although there are 24 hours in a day
22
25
  # (0-23) and 60 minutes in an hour (0-59), <tt>Clock</tt> calculates
23
26
  # the full hours and remaining minutes of whatever is supplied.
24
27
  #
28
+ # @param [Integer] hour number of hours
29
+ # @param [Integer] min number of minutes
30
+ #
25
31
  def initialize(hour=0,min=0)
26
32
  @hour=hour
27
33
  @min=min
@@ -30,34 +36,43 @@ module Workpattern
30
36
  @min=total_minutes % 60
31
37
  end
32
38
 
33
- # :call-seq: minutes => Integer
34
- # returns the total number of minutes
39
+ # Returns the total number of minutes
40
+ #
41
+ # @return [Integer] total minutes represented by the Clock object
35
42
  #
36
43
  def minutes
37
44
  return (@hour*60)+@min
38
45
  end
39
46
 
40
- # :call-seq: hour => Integer
41
- # returns the hour of the clock (0-23)
47
+ # Returns the hour of the clock (0-23)
48
+ #
49
+ # @return [Integer] hour of Clock from 0 to 23.
42
50
  #
43
51
  def hour
44
52
  return @hour % 24
45
53
  end
46
54
 
47
- # :call-seq: min => Integer
48
- # returns the minute of the clock (0-59)
55
+ # Returns the minute of the clock (0-59)
56
+ #
57
+ # @return [Integer] minute of Clock from 0 to 59
49
58
  #
50
59
  def min
51
60
  return @min % 60
52
61
  end
53
62
 
54
- # :call-seq: time => DateTime
55
- # returns a <tt>Time</tt> object with the correct
63
+ # Returns a <tt>Time</tt> object with the correct
56
64
  # <tt>hour</tt> and <tt>min</tt> values. The date
57
- # is 10th June 1963
58
- #
65
+ # is 10th June 1963.
66
+ #
67
+ # @return [DateTime] The time using the date of 10th June 1963 (My Birthday)
59
68
  def time
60
69
  return DateTime.new(1963,6,10,hour,min)
61
- end
70
+ end
71
+
72
+
73
+ # @return [String] representation of <tt>Clock</tt> value as 'hh:mn minutes'
74
+ def to_s
75
+ hour.to_s.concat(':').concat(min.to_s).concat(' ').concat(minutes.to_s)
76
+ end
62
77
  end
63
78
  end