workpattern 0.3.0 → 0.3.1
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.
- data/CHANGELOG +4 -0
- data/README.md +48 -3
- data/lib/workpattern.rb +58 -134
- data/lib/workpattern/clock.rb +40 -25
- data/lib/workpattern/day.rb +93 -29
- data/lib/workpattern/hour.rb +65 -26
- data/lib/workpattern/utility/base.rb +20 -2
- data/lib/workpattern/version.rb +3 -1
- data/lib/workpattern/week.rb +50 -35
- data/lib/workpattern/workpattern.rb +125 -78
- metadata +2 -2
    
        data/lib/workpattern/day.rb
    CHANGED
    
    | @@ -1,13 +1,33 @@ | |
| 1 1 | 
             
            module Workpattern
         | 
| 2 | 
            -
               | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              # @author Barrie Callender
         | 
| 4 | 
            +
              # @!attribute values
         | 
| 5 | 
            +
              #   @return [Array] each hour of the day
         | 
| 6 | 
            +
              # @!attribute hours
         | 
| 7 | 
            +
              #   @return [Integer] number of hours in the day
         | 
| 8 | 
            +
              # @!attribute first_hour
         | 
| 9 | 
            +
              #   @return [Integer] first working hour in the day
         | 
| 10 | 
            +
              # @!attribute first_min
         | 
| 11 | 
            +
              #   @return [Integer] first working minute in first working hour in the day
         | 
| 12 | 
            +
              # @!attribute last_hour
         | 
| 13 | 
            +
              #   @return [Integer] last working hour in the day
         | 
| 14 | 
            +
              # @!attribute last_min
         | 
| 15 | 
            +
              #   @return [Integer] last working minute in last working hour in the day
         | 
| 16 | 
            +
              # @!attribute total
         | 
| 17 | 
            +
              #   @return [Integer] total number of minutes in the day
         | 
| 18 | 
            +
              #  
         | 
| 19 | 
            +
              # Represents the 24 hours of a day.
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              # @since 0.2.0
         | 
| 22 | 
            +
              # @todo implement a day with different number of hours in it to support daylight saving
         | 
| 3 23 | 
             
              #
         | 
| 4 24 | 
             
              class Day
         | 
| 5 25 | 
             
                include Workpattern::Utility
         | 
| 6 26 | 
             
                attr_accessor :values, :hours, :first_hour, :first_min, :last_hour, :last_min, :total
         | 
| 7 27 |  | 
| 8 | 
            -
                #  | 
| 9 | 
            -
                # | 
| 10 | 
            -
                #  | 
| 28 | 
            +
                # The new <tt>Day</tt> object can be created as either working or resting.
         | 
| 29 | 
            +
                #
         | 
| 30 | 
            +
                # @param [Integer] type is working (1) or resting (0)
         | 
| 11 31 | 
             
                #
         | 
| 12 32 | 
             
                def initialize(type=1)
         | 
| 13 33 | 
             
                  @hours=24
         | 
| @@ -18,9 +38,10 @@ module Workpattern | |
| 18 38 | 
             
                  set_attributes
         | 
| 19 39 | 
             
                end
         | 
| 20 40 |  | 
| 21 | 
            -
                # :call-seq: duplicate => Day
         | 
| 22 41 | 
             
                # Creates a duplicate of the current <tt>Day</tt> instance.
         | 
| 23 42 | 
             
                #
         | 
| 43 | 
            +
                # @return [Day] 
         | 
| 44 | 
            +
                #
         | 
| 24 45 | 
             
                def duplicate
         | 
| 25 46 | 
             
                  duplicate_day = Day.new()
         | 
| 26 47 | 
             
                  duplicate_values=Array.new(@values.size)
         | 
| @@ -38,21 +59,18 @@ module Workpattern | |
| 38 59 | 
             
                  return duplicate_day
         | 
| 39 60 | 
             
                end
         | 
| 40 61 |  | 
| 41 | 
            -
                # :call-seq: refresh
         | 
| 42 62 | 
             
                # Recalculates characteristics for this day
         | 
| 43 63 | 
             
                #
         | 
| 44 64 | 
             
                def refresh
         | 
| 45 65 | 
             
                  set_attributes
         | 
| 46 66 | 
             
                end
         | 
| 47 67 |  | 
| 48 | 
            -
                # :call-seq: workpattern(start_time,finish_time,type)
         | 
| 49 68 | 
             
                # Sets all minutes in a date range to be working or resting.
         | 
| 50 | 
            -
                # The <tt>start_time</tt> and <tt>finish_time</tt> need to have 
         | 
| 51 | 
            -
                # <tt>#hour</tt> and <tt>#min</tt> methods to return the time 
         | 
| 52 | 
            -
                # in hours and minutes respectively.
         | 
| 53 69 | 
             
                #
         | 
| 54 | 
            -
                #  | 
| 55 | 
            -
                # 
         | 
| 70 | 
            +
                # @param [(#hour,#min)] start_time is the start of the range to set
         | 
| 71 | 
            +
                # @param [(#hour, #min)] finish_time is the finish of the range to be set
         | 
| 72 | 
            +
                # @param [Integer] type is either working (1) or resting (0)
         | 
| 73 | 
            +
                #
         | 
| 56 74 | 
             
                def workpattern(start_time,finish_time,type)
         | 
| 57 75 |  | 
| 58 76 | 
             
                  if start_time.hour==finish_time.hour
         | 
| @@ -71,15 +89,22 @@ module Workpattern | |
| 71 89 | 
             
                  set_attributes
         | 
| 72 90 | 
             
                end
         | 
| 73 91 |  | 
| 74 | 
            -
                # :call-seq: calc(time,duration) => time, duration
         | 
| 75 | 
            -
                #
         | 
| 76 92 | 
             
                # Calculates the result of adding <tt>duration</tt> to
         | 
| 77 93 | 
             
                # <tt>time</tt>.  The <tt>duration</tt> can be negative in
         | 
| 78 94 | 
             
                # which case it subtracts from <tt>time</tt>.
         | 
| 79 95 | 
             
                #
         | 
| 80 96 | 
             
                # An addition where there are less working minutes left in 
         | 
| 81 97 | 
             
                # the day than are being added will result in the time 
         | 
| 82 | 
            -
                # returned  | 
| 98 | 
            +
                # returned being 00:00 on the following day.
         | 
| 99 | 
            +
                #
         | 
| 100 | 
            +
                # A subtraction where there are less working minutes left in
         | 
| 101 | 
            +
                # the day than are being added will result in the time 
         | 
| 102 | 
            +
                # returned being the previous day with the <tt>midnight</tt> flag set to true.
         | 
| 103 | 
            +
                #
         | 
| 104 | 
            +
                # @param [DateTime] time when the calculation starts from
         | 
| 105 | 
            +
                # @param [Integer] duration is the number of minutes to add or subtract if it is negative
         | 
| 106 | 
            +
                # @param [Boolean] midnight is a flag used in subtraction to pretend the time is actually midnight
         | 
| 107 | 
            +
                # @return [DateTime,Integer,Boolean] Calculated time along with any remaining duration and the midnight flag
         | 
| 83 108 | 
             
                # 
         | 
| 84 109 | 
             
                def calc(time,duration,midnight=false)
         | 
| 85 110 |  | 
| @@ -93,17 +118,21 @@ module Workpattern | |
| 93 118 |  | 
| 94 119 | 
             
                end
         | 
| 95 120 |  | 
| 96 | 
            -
                #  | 
| 97 | 
            -
                # | 
| 121 | 
            +
                # Returns true if the given minute is working and false if it is resting
         | 
| 122 | 
            +
                #
         | 
| 123 | 
            +
                # @param [(#hour, #min)] start is the time in the day to inspect
         | 
| 124 | 
            +
                # @return [Boolean] true if the time is working and false if it is resting
         | 
| 98 125 | 
             
                #
         | 
| 99 126 | 
             
                def working?(start)
         | 
| 100 127 | 
             
                  return true if minutes(start.hour,start.min,start.hour,start.min)==1
         | 
| 101 128 | 
             
                  return false
         | 
| 102 129 | 
             
                end
         | 
| 103 130 |  | 
| 104 | 
            -
                #  | 
| 105 | 
            -
                # | 
| 106 | 
            -
                #  | 
| 131 | 
            +
                # Returns the difference in working minutes between two times.
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                # @param [(#hour, #min)] start start time in the range
         | 
| 134 | 
            +
                # @param [(#hour, #min)] finish finish time in the range
         | 
| 135 | 
            +
                # @return [Integer] number of working minutes
         | 
| 107 136 | 
             
                #
         | 
| 108 137 | 
             
                def diff(start,finish)
         | 
| 109 138 | 
             
                  start,finish=finish,start if ((start <=> finish))==1
         | 
| @@ -120,9 +149,16 @@ module Workpattern | |
| 120 149 | 
             
                  return duration, start
         | 
| 121 150 | 
             
                end
         | 
| 122 151 |  | 
| 123 | 
            -
                #  | 
| 124 | 
            -
                # | 
| 125 | 
            -
                # 
         | 
| 152 | 
            +
                # Returns the total number of minutes between two times.
         | 
| 153 | 
            +
                #
         | 
| 154 | 
            +
                # @param [Integer] start_hour first hour in range
         | 
| 155 | 
            +
                # @param [Integer] start_min first minute of first hour in range
         | 
| 156 | 
            +
                # @param [Integer] finish_hour last hour in range
         | 
| 157 | 
            +
                # @param [Integer] finish_min last minute of last hour in range
         | 
| 158 | 
            +
                # @return [Integer] minutes between supplied hours and minutes
         | 
| 159 | 
            +
                #
         | 
| 160 | 
            +
                # @todo can this method and #diff method be combined?
         | 
| 161 | 
            +
                #
         | 
| 126 162 | 
             
                def minutes(start_hour,start_min,finish_hour,finish_min)
         | 
| 127 163 |  | 
| 128 164 | 
             
                  if (start_hour > finish_hour) || ((finish_hour==start_hour) && (start_min > finish_min))
         | 
| @@ -146,6 +182,8 @@ module Workpattern | |
| 146 182 |  | 
| 147 183 | 
             
                private
         | 
| 148 184 |  | 
| 185 | 
            +
                # Calculates the attributes that describe the day.  Called after changes.
         | 
| 186 | 
            +
                #
         | 
| 149 187 | 
             
                def set_attributes
         | 
| 150 188 | 
             
                  @first_hour=nil
         | 
| 151 189 | 
             
                  @first_min=nil
         | 
| @@ -161,6 +199,12 @@ module Workpattern | |
| 161 199 | 
             
                  }
         | 
| 162 200 | 
             
                end
         | 
| 163 201 |  | 
| 202 | 
            +
                # Returns the first working minute as a <tt>DateTime</tt> or <tt>oo:oo</tt>
         | 
| 203 | 
            +
                # when there is no working minutes in the day.  Used by the <tt>#subtract</tt> method
         | 
| 204 | 
            +
                #
         | 
| 205 | 
            +
                # @param [DateTime] time day for which the first working time is sought.
         | 
| 206 | 
            +
                # @return [DateTime] the first working time of the day
         | 
| 207 | 
            +
                #
         | 
| 164 208 | 
             
                def first_working_minute(time)
         | 
| 165 209 | 
             
                  if @first_hour.nil?
         | 
| 166 210 | 
             
                    return time - (HOUR*time.hour) - (MINUTE*time.min)
         | 
| @@ -171,6 +215,13 @@ module Workpattern | |
| 171 215 | 
             
                  end  
         | 
| 172 216 | 
             
                end
         | 
| 173 217 |  | 
| 218 | 
            +
                # Handles the subtraction of a duration from a time in the day.
         | 
| 219 | 
            +
                # 
         | 
| 220 | 
            +
                # @param [DateTime] time when the subtraction starts from
         | 
| 221 | 
            +
                # @param [Integer] duration is the number of minutes to subtract from the <tt>time</tt>
         | 
| 222 | 
            +
                # @param [Boolean] midnight is a flag used in subtraction to pretend the time is actually midnight
         | 
| 223 | 
            +
                # @return [DateTime,Integer,Boolean] Calculated time along with any remaining duration and the midnight flag
         | 
| 224 | 
            +
                #
         | 
| 174 225 | 
             
                def subtract(time,duration,midnight=false)    
         | 
| 175 226 | 
             
                  if (time.hour==0 && time.min==0)
         | 
| 176 227 | 
             
                    if midnight      
         | 
| @@ -213,10 +264,13 @@ module Workpattern | |
| 213 264 | 
             
                  return time,duration, false
         | 
| 214 265 | 
             
                end
         | 
| 215 266 |  | 
| 216 | 
            -
                # 
         | 
| 217 | 
            -
                # Returns the result of adding #duration to the specified time
         | 
| 267 | 
            +
                # Returns the result of adding <tt>duration</tt> to the given <tt>time</tt>
         | 
| 218 268 | 
             
                # When there are not enough minutes in the day it returns the date
         | 
| 219 | 
            -
                # for the start of the following
         | 
| 269 | 
            +
                # for the start of the following day.
         | 
| 270 | 
            +
                #
         | 
| 271 | 
            +
                # @param [DateTime] time when the calculation starts from
         | 
| 272 | 
            +
                # @param [Integer] duration is the number of minutes to add
         | 
| 273 | 
            +
                # @return [DateTime,Integer] Calculated time along with any remaining duration
         | 
| 220 274 | 
             
                #
         | 
| 221 275 | 
             
                def add(time,duration)
         | 
| 222 276 | 
             
                  available_minutes=minutes(time.hour,time.min,@hours-1,59)   
         | 
| @@ -245,16 +299,26 @@ module Workpattern | |
| 245 299 | 
             
                  return result_date,duration, false
         | 
| 246 300 | 
             
                end
         | 
| 247 301 |  | 
| 302 | 
            +
                # Returns the start of the next hour.
         | 
| 303 | 
            +
                #
         | 
| 304 | 
            +
                # The next hour could be the start of the following day.
         | 
| 305 | 
            +
                #
         | 
| 306 | 
            +
                # @param [DateTime] start is the <tt>DateTime</tt> for which the following hour is required.
         | 
| 307 | 
            +
                # @return [DateTime] the start of the next hour following the <tt>DateTime</tt> supplied
         | 
| 308 | 
            +
                #
         | 
| 248 309 | 
             
                def next_hour(start)
         | 
| 249 310 | 
             
                  return start+HOUR-(start.min*MINUTE) 
         | 
| 250 311 | 
             
                end
         | 
| 251 312 |  | 
| 313 | 
            +
                # Returns the number of working minutes left in the current hour
         | 
| 314 | 
            +
                #
         | 
| 315 | 
            +
                # @param [DateTime] start is the <tt>DateTime</tt> for which the remaining working minutes 
         | 
| 316 | 
            +
                #                   in the hour are required
         | 
| 317 | 
            +
                # @return [Integer] number of remaining working minutes
         | 
| 318 | 
            +
                #
         | 
| 252 319 | 
             
                def minutes_left_in_hour(start)
         | 
| 253 320 | 
             
                  return @values[start.hour].diff(start.min,60)
         | 
| 254 321 | 
             
                end
         | 
| 255 322 |  | 
| 256 | 
            -
                def minutes_left_in_day(start)
         | 
| 257 | 
            -
                  start.hour
         | 
| 258 | 
            -
                end  
         | 
| 259 323 | 
             
              end
         | 
| 260 324 | 
             
            end
         | 
    
        data/lib/workpattern/hour.rb
    CHANGED
    
    | @@ -1,60 +1,76 @@ | |
| 1 1 | 
             
            module Workpattern
         | 
| 2 2 |  | 
| 3 | 
            -
              # Represents the 60 minutes of an hour using  | 
| 3 | 
            +
              # Represents the 60 minutes of an hour using an <tt>Integer</tt>
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # @since 0.2.0
         | 
| 4 6 | 
             
              #
         | 
| 5 7 | 
             
              module Hour
         | 
| 6 8 |  | 
| 7 | 
            -
                # :call-seq: total => Integer
         | 
| 8 9 | 
             
                # Returns the total working minutes in the hour
         | 
| 9 | 
            -
                # | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                # @return [Integer] working minutes in the hour 
         | 
| 12 | 
            +
                #
         | 
| 10 13 | 
             
                def total
         | 
| 11 14 | 
             
                  return minutes(0,59)
         | 
| 12 15 | 
             
                end  
         | 
| 13 16 |  | 
| 14 | 
            -
                # :call-seq: workpattern(start,finish,type) => Fixnum
         | 
| 15 17 | 
             
                # Sets the minutes to either working (type=1) or resting (type=0)
         | 
| 18 | 
            +
                # 
         | 
| 19 | 
            +
                # @param [Integer] start minute at start of range
         | 
| 20 | 
            +
                # @param [Integer] finish minute at end of range
         | 
| 21 | 
            +
                # @param [Integer] type defines whether working (1) or resting (0)
         | 
| 16 22 | 
             
                #
         | 
| 17 23 | 
             
                def workpattern(start,finish,type)
         | 
| 18 24 | 
             
                  return working(start,finish) if type==1
         | 
| 19 25 | 
             
                  return resting(start,finish) if type==0
         | 
| 20 26 | 
             
                end
         | 
| 21 27 |  | 
| 22 | 
            -
                #  | 
| 23 | 
            -
                # | 
| 28 | 
            +
                # Returns the first working minute in the hour or 60 if there are no working minutes
         | 
| 29 | 
            +
                #
         | 
| 30 | 
            +
                # @return [Integer] first working minute or 60 if none found
         | 
| 24 31 | 
             
                #
         | 
| 25 32 | 
             
                def first
         | 
| 26 33 | 
             
                  0.upto(59) {|minute| return minute if self.minutes(minute,minute)==1}
         | 
| 27 34 | 
             
                  return nil
         | 
| 28 35 | 
             
                end
         | 
| 29 36 |  | 
| 30 | 
            -
                #  | 
| 31 | 
            -
                # | 
| 37 | 
            +
                # Returns the last working minute in the hour or nil if there are no working minutes
         | 
| 38 | 
            +
                #
         | 
| 39 | 
            +
                # @return [Integer] last working minute or nil if none found
         | 
| 32 40 | 
             
                #
         | 
| 33 41 | 
             
                def last
         | 
| 34 42 | 
             
                  59.downto(0) {|minute| return minute if self.minutes(minute,minute)==1}
         | 
| 35 43 | 
             
                  return nil
         | 
| 36 44 | 
             
                end
         | 
| 37 45 |  | 
| 38 | 
            -
                # :call-seq: working?(start) => Boolean
         | 
| 39 46 | 
             
                # Returns true if the given minute is working and false if it isn't
         | 
| 47 | 
            +
                # 
         | 
| 48 | 
            +
                # @param [Integer] start is the minute being tested
         | 
| 49 | 
            +
                # @return [Boolean] true if minute is working, otherwise false
         | 
| 40 50 | 
             
                #
         | 
| 41 51 | 
             
                def working?(start)
         | 
| 42 52 | 
             
                  return true if minutes(start,start)==1
         | 
| 43 53 | 
             
                  return false
         | 
| 44 54 | 
             
                end
         | 
| 45 55 |  | 
| 46 | 
            -
                # :call-seq: minutes(start,finish) => Integer
         | 
| 47 56 | 
             
                # Returns the total number of minutes between and including two minutes
         | 
| 48 57 | 
             
                #
         | 
| 58 | 
            +
                # @param [Integer] start first minute in range
         | 
| 59 | 
            +
                # @param [Integer] finish last minute in range
         | 
| 60 | 
            +
                # @return [Integer] number of minutes from <tt>start</tt> to <tt>finish</tt> inclusive
         | 
| 61 | 
            +
                #
         | 
| 49 62 | 
             
                def minutes(start,finish)
         | 
| 50 63 | 
             
                  start,finish=finish,start if start > finish
         | 
| 51 64 | 
             
                  return (self & mask(start,finish)).to_s(2).count('1')
         | 
| 52 65 | 
             
                end
         | 
| 53 66 |  | 
| 54 | 
            -
                #  | 
| 55 | 
            -
                #  | 
| 56 | 
            -
                # | 
| 57 | 
            -
                #  | 
| 67 | 
            +
                # Returns the DateTime and remainding minutes when adding a duration to a minute in the hour. 
         | 
| 68 | 
            +
                # A negative duration will subtract the minutes.
         | 
| 69 | 
            +
                #
         | 
| 70 | 
            +
                # @param [DateTime] time is the full date but only the minute element is used
         | 
| 71 | 
            +
                # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
         | 
| 72 | 
            +
                # @param [Boolean] next_hour used in subtraction to specify the starting point as midnight (00:00 the next day)
         | 
| 73 | 
            +
                # @return [DateTime,Integer,Boolean] The <tt>DateTime</tt> calculated along with remaining minutes and a flag indicating if starting point is next hour
         | 
| 58 74 | 
             
                #
         | 
| 59 75 | 
             
                def calc(time,duration,next_hour=false)
         | 
| 60 76 |  | 
| @@ -67,8 +83,10 @@ module Workpattern | |
| 67 83 | 
             
                  end 
         | 
| 68 84 | 
             
                end
         | 
| 69 85 |  | 
| 70 | 
            -
                #  | 
| 71 | 
            -
                #  | 
| 86 | 
            +
                # Returns the number of minutes between two minutes
         | 
| 87 | 
            +
                # @param [Integer] start first minute in range
         | 
| 88 | 
            +
                # @param [Integer] finish last minute in range
         | 
| 89 | 
            +
                # @return [Integer] number of working minutes in the range
         | 
| 72 90 | 
             
                #
         | 
| 73 91 | 
             
                def diff(start,finish)
         | 
| 74 92 | 
             
                  start,finish=finish,start if start > finish
         | 
| @@ -78,22 +96,39 @@ module Workpattern | |
| 78 96 |  | 
| 79 97 | 
             
                private
         | 
| 80 98 |  | 
| 81 | 
            -
                #  | 
| 99 | 
            +
                # Sets a working pattern
         | 
| 100 | 
            +
                #
         | 
| 101 | 
            +
                # @param [Integer] start is first minute in the range
         | 
| 102 | 
            +
                # @param [Integer] finish is last minute in the range
         | 
| 103 | 
            +
                #
         | 
| 82 104 | 
             
                def working(start,finish)
         | 
| 83 105 | 
             
                  return self | mask(start,finish)
         | 
| 84 106 | 
             
                end
         | 
| 85 107 |  | 
| 86 | 
            -
                # sets resting pattern
         | 
| 108 | 
            +
                # sets a resting pattern
         | 
| 109 | 
            +
                #
         | 
| 110 | 
            +
                # @param [Integer] start is first minute in the range
         | 
| 111 | 
            +
                # @param [Integer] finish is last minute in the range
         | 
| 112 | 
            +
                #
         | 
| 87 113 | 
             
                def resting(start,finish)
         | 
| 88 114 | 
             
                  return self & ((2**60-1)-mask(start,finish))
         | 
| 89 115 | 
             
                end
         | 
| 90 116 |  | 
| 91 | 
            -
                #  | 
| 117 | 
            +
                # Creates a bit mask of 1's over the specified range
         | 
| 118 | 
            +
                #
         | 
| 119 | 
            +
                # @param [Integer] start is first minute in the range
         | 
| 120 | 
            +
                # @param [Integer] finish is the last minute in the range
         | 
| 121 | 
            +
                #
         | 
| 92 122 | 
             
                def mask(start,finish)
         | 
| 93 123 | 
             
                  return ((2**(finish+1)-1)-(2**start-1))
         | 
| 94 124 | 
             
                end
         | 
| 95 125 |  | 
| 96 | 
            -
                #  | 
| 126 | 
            +
                # Handles the addition of minutes to a time
         | 
| 127 | 
            +
                #
         | 
| 128 | 
            +
                # @param [DateTime] time is the full date but only the minute element is used
         | 
| 129 | 
            +
                # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
         | 
| 130 | 
            +
                # @return [DateTime, Integer] The resulting DateTime and any remaining minutes
         | 
| 131 | 
            +
                #
         | 
| 97 132 | 
             
                def add(time,duration)
         | 
| 98 133 | 
             
                  start = time.min
         | 
| 99 134 | 
             
                  available_minutes=minutes(start,59)
         | 
| @@ -121,7 +156,12 @@ module Workpattern | |
| 121 156 | 
             
                  return result_date, result_remainder  
         | 
| 122 157 | 
             
                end
         | 
| 123 158 |  | 
| 124 | 
            -
                #  | 
| 159 | 
            +
                # Handles the subtraction of minutes from a time.
         | 
| 160 | 
            +
                # @param [DateTime] time is the full date but only the minute element is used
         | 
| 161 | 
            +
                # @param [Integer] duration is the number of minutes to add and can be negative (subtraction)
         | 
| 162 | 
            +
                # @param [Boolean] next_hour indicates if the 59th second is the first one to be included
         | 
| 163 | 
            +
                # @return [DateTime, Integer] The resulting DateTime and any remaining minutes
         | 
| 164 | 
            +
                #
         | 
| 125 165 | 
             
                def subtract(time,duration,next_hour)
         | 
| 126 166 | 
             
                  if next_hour
         | 
| 127 167 | 
             
                    if working?(59)
         | 
| @@ -157,10 +197,9 @@ module Workpattern | |
| 157 197 | 
             
              end
         | 
| 158 198 | 
             
            end
         | 
| 159 199 |  | 
| 160 | 
            -
            class  | 
| 200 | 
            +
            # Hours are represented by a bitwise <tt>Integer</tt> class so the code is mixed in to that class
         | 
| 201 | 
            +
            # @ since 0.3.0
         | 
| 202 | 
            +
            #
         | 
| 203 | 
            +
            class Integer
         | 
| 161 204 | 
             
              include Workpattern::Hour
         | 
| 162 205 | 
             
            end
         | 
| 163 | 
            -
            class Bignum
         | 
| 164 | 
            -
              include Workpattern::Hour
         | 
| 165 | 
            -
            end
         | 
| 166 | 
            -
              
         | 
| @@ -1,11 +1,29 @@ | |
| 1 1 | 
             
            module Workpattern
         | 
| 2 | 
            -
             | 
| 2 | 
            +
             | 
| 3 | 
            +
              # Mixins expected to be used in more than one class
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # @since 0.2.0
         | 
| 6 | 
            +
              #
         | 
| 3 7 | 
             
              module Utility
         | 
| 4 | 
            -
             | 
| 8 | 
            +
             | 
| 9 | 
            +
                # Returns the supplied <tt>DateTime</tt> at the very start of the day.
         | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                # @param [DateTime] adate is the <tt>DateTime</tt> to be changed
         | 
| 12 | 
            +
                # @return [DateTime] 
         | 
| 13 | 
            +
                # 
         | 
| 14 | 
            +
                # @todo Consider mixin for DateTime class 
         | 
| 15 | 
            +
                #
         | 
| 5 16 | 
             
                def midnight_before(adate)
         | 
| 6 17 | 
             
                  return adate -(HOUR * adate.hour) - (MINUTE * adate.min)
         | 
| 7 18 | 
             
                end
         | 
| 8 19 |  | 
| 20 | 
            +
                # Returns the supplied <tt>DateTime</tt> at the very start of the next day.
         | 
| 21 | 
            +
                #
         | 
| 22 | 
            +
                # @param [DateTime] adate is the <tt>DateTime</tt> to be changed
         | 
| 23 | 
            +
                # @return [DateTime] 
         | 
| 24 | 
            +
                # 
         | 
| 25 | 
            +
                # @todo Consider mixin for DateTime class  
         | 
| 26 | 
            +
                #
         | 
| 9 27 | 
             
                def midnight_after(adate)
         | 
| 10 28 | 
             
                  return midnight_before(adate.next_day)
         | 
| 11 29 | 
             
                end
         | 
    
        data/lib/workpattern/version.rb
    CHANGED
    
    
    
        data/lib/workpattern/week.rb
    CHANGED
    
    | @@ -4,26 +4,29 @@ module Workpattern | |
| 4 4 | 
             
              # @!attribute values
         | 
| 5 5 | 
             
              #   @return [Array] each day of the week
         | 
| 6 6 | 
             
              # @!attribute days
         | 
| 7 | 
            -
              #   @return [ | 
| 7 | 
            +
              #   @return [Integer] number of days in the week
         | 
| 8 8 | 
             
              # @!attribute start
         | 
| 9 9 | 
             
              #   @return [DateTime] first date in the range
         | 
| 10 10 | 
             
              # @!attribute finish
         | 
| 11 11 | 
             
              #   @return [DateTime] last date in the range
         | 
| 12 12 | 
             
              # @!attribute week_total
         | 
| 13 | 
            -
              #   @return [ | 
| 13 | 
            +
              #   @return [Integer] total number of minutes in a week
         | 
| 14 14 | 
             
              # @!attribute total
         | 
| 15 | 
            -
              #   @return [ | 
| 15 | 
            +
              #   @return [Integer] total number of minutes in the range
         | 
| 16 16 | 
             
              #  
         | 
| 17 17 | 
             
              # Represents working and resting periods for each day in a week for a specified date range.
         | 
| 18 18 | 
             
              #
         | 
| 19 | 
            +
              # @since 0.2.0
         | 
| 20 | 
            +
              #
         | 
| 19 21 | 
             
              class Week
         | 
| 20 22 |  | 
| 21 23 | 
             
                attr_accessor :values, :days, :start, :finish, :week_total, :total
         | 
| 22 24 |  | 
| 23 | 
            -
                #  | 
| 25 | 
            +
                # The new <tt>Week</tt> object can be created as either working or resting.
         | 
| 26 | 
            +
                #
         | 
| 24 27 | 
             
                # @param [DateTime] start first date in the range
         | 
| 25 28 | 
             
                # @param [DateTime] finish last date in the range
         | 
| 26 | 
            -
                # @param [ | 
| 29 | 
            +
                # @param [Integer] type working (1) or resting (0)
         | 
| 27 30 | 
             
                # @return [Week] newly initialised Week object    
         | 
| 28 31 | 
             
                #
         | 
| 29 32 | 
             
                def initialize(start,finish,type=1)
         | 
| @@ -36,8 +39,9 @@ module Workpattern | |
| 36 39 | 
             
                  set_attributes
         | 
| 37 40 | 
             
                end
         | 
| 38 41 |  | 
| 39 | 
            -
                # Duplicates the current Week object
         | 
| 40 | 
            -
                # | 
| 42 | 
            +
                # Duplicates the current <tt>Week</tt> object
         | 
| 43 | 
            +
                #
         | 
| 44 | 
            +
                # @return [Week] a duplicated instance of the current <tt>Week</tt> object
         | 
| 41 45 | 
             
                #
         | 
| 42 46 | 
             
                def duplicate()
         | 
| 43 47 | 
             
                  duplicate_week=Week.new(@start,@finish)
         | 
| @@ -55,15 +59,18 @@ module Workpattern | |
| 55 59 | 
             
                  return duplicate_week
         | 
| 56 60 | 
             
                end
         | 
| 57 61 |  | 
| 58 | 
            -
                # Recalculates the attributes that  | 
| 59 | 
            -
                # This was made public for  | 
| 62 | 
            +
                # Recalculates the attributes that define a <tt>Week</tt> object.
         | 
| 63 | 
            +
                # This was made public for <tt>#duplicate</tt> to work
         | 
| 60 64 | 
             
                #
         | 
| 61 65 | 
             
                def refresh
         | 
| 62 66 | 
             
                  set_attributes
         | 
| 63 67 | 
             
                end
         | 
| 64 68 |  | 
| 65 69 | 
             
                # Changes the date range.
         | 
| 66 | 
            -
                # This method calls  | 
| 70 | 
            +
                # This method calls <tt>#refresh</tt> to update the attributes.
         | 
| 71 | 
            +
                #
         | 
| 72 | 
            +
                # @param [DateTime] start is the new starting date for the <tt>Week</tt>
         | 
| 73 | 
            +
                # @param [DateTime] finish is the new finish date for the <tt>Week</tt>    
         | 
| 67 74 | 
             
                #
         | 
| 68 75 | 
             
                def adjust(start,finish)
         | 
| 69 76 | 
             
                  @start=DateTime.new(start.year,start.month,start.day)
         | 
| @@ -73,18 +80,21 @@ module Workpattern | |
| 73 80 |  | 
| 74 81 | 
             
                # Sets a range of minutes in a week to be working or resting.  The parameters supplied
         | 
| 75 82 | 
             
                # to this method determine exactly what should be changed
         | 
| 76 | 
            -
                # | 
| 83 | 
            +
                #
         | 
| 84 | 
            +
                # @param [Hash(DAYNAMES)] days identifies the days to be included in the range
         | 
| 77 85 | 
             
                # @param [DateTime] from_time where the time portion is used to specify the first minute to be set
         | 
| 78 86 | 
             
                # @param [DateTime] to_time where the time portion is used to specify the last minute to be set
         | 
| 79 | 
            -
                # @param [ | 
| 87 | 
            +
                # @param [Integer] type where a 1 sets it to working and a 0 to resting
         | 
| 88 | 
            +
                #
         | 
| 80 89 | 
             
                def workpattern(days,from_time,to_time,type)
         | 
| 81 90 | 
             
                  DAYNAMES[days].each {|day| @values[day].workpattern(from_time,to_time,type)}  
         | 
| 82 91 | 
             
                  refresh
         | 
| 83 92 | 
             
                end
         | 
| 84 93 |  | 
| 85 94 | 
             
                # Calculates a new date by adding or subtracting a duration in minutes.
         | 
| 95 | 
            +
                #
         | 
| 86 96 | 
             
                # @param [DateTime] start original date
         | 
| 87 | 
            -
                # @param [ | 
| 97 | 
            +
                # @param [Integer] duration minutes to add or subtract
         | 
| 88 98 | 
             
                # @param [Boolean] midnight flag used for subtraction that indicates the start date is midnight
         | 
| 89 99 | 
             
                #
         | 
| 90 100 | 
             
                def calc(start,duration, midnight=false)
         | 
| @@ -94,13 +104,14 @@ module Workpattern | |
| 94 104 | 
             
                  return subtract(start,duration, midnight) if duration <0  
         | 
| 95 105 | 
             
                end
         | 
| 96 106 |  | 
| 97 | 
            -
                # Comparison  | 
| 107 | 
            +
                # Comparison Returns an integer (-1, 0, or +1) if week is less than, equal to, or greater than other_week
         | 
| 108 | 
            +
                #
         | 
| 98 109 | 
             
                # @param [Week] other_week object to compare to
         | 
| 99 110 | 
             
                # @return [Integer] -1,0 or +1 if week is less than, equal to or greater than other_week
         | 
| 100 | 
            -
                def <=>( | 
| 101 | 
            -
                  if @start <  | 
| 111 | 
            +
                def <=>(other_week)
         | 
| 112 | 
            +
                  if @start < other_week.start
         | 
| 102 113 | 
             
                    return -1
         | 
| 103 | 
            -
                  elsif @start ==  | 
| 114 | 
            +
                  elsif @start == other_week.start
         | 
| 104 115 | 
             
                    return 0
         | 
| 105 116 | 
             
                  else
         | 
| 106 117 | 
             
                    return 1
         | 
| @@ -108,6 +119,7 @@ module Workpattern | |
| 108 119 | 
             
                end
         | 
| 109 120 |  | 
| 110 121 | 
             
                # Returns true if the supplied DateTime is working and false if resting
         | 
| 122 | 
            +
                #
         | 
| 111 123 | 
             
                # @param [DateTime] start DateTime to be tested
         | 
| 112 124 | 
             
                # @return [Boolean] true if the minute is working otherwise false if it is a resting minute
         | 
| 113 125 | 
             
                #
         | 
| @@ -116,10 +128,10 @@ module Workpattern | |
| 116 128 | 
             
                end    
         | 
| 117 129 |  | 
| 118 130 | 
             
                # Returns the difference in minutes between two DateTime values.
         | 
| 131 | 
            +
                #
         | 
| 119 132 | 
             
                # @param [DateTime] start starting DateTime
         | 
| 120 133 | 
             
                # @param [DateTime] finish ending DateTime
         | 
| 121 | 
            -
                # @return [ | 
| 122 | 
            -
                # @return [DateTime] start date for rest of calculation.  The calculation is complete when this is the same as the finish date
         | 
| 134 | 
            +
                # @return [Integer, DateTime] number of minutes and start date for rest of calculation.
         | 
| 123 135 | 
             
                #
         | 
| 124 136 | 
             
                def diff(start,finish)
         | 
| 125 137 | 
             
                  start,finish=finish,start if ((start <=> finish))==1
         | 
| @@ -159,9 +171,10 @@ module Workpattern | |
| 159 171 | 
             
                end
         | 
| 160 172 |  | 
| 161 173 | 
             
                # Calculates the total number of minutes between two dates
         | 
| 174 | 
            +
                #
         | 
| 162 175 | 
             
                # @param [DateTime] start is the first date in the range
         | 
| 163 176 | 
             
                # @param [DateTime] finish is the last date in the range
         | 
| 164 | 
            -
                # @return [ | 
| 177 | 
            +
                # @return [Integer] total number of minutes between supplied dates
         | 
| 165 178 | 
             
                #
         | 
| 166 179 | 
             
                def total_hours(start,finish)
         | 
| 167 180 | 
             
                  total=0
         | 
| @@ -171,13 +184,13 @@ module Workpattern | |
| 171 184 | 
             
                  return total
         | 
| 172 185 | 
             
                end
         | 
| 173 186 |  | 
| 174 | 
            -
                # Adds a duration in minutes to a date
         | 
| 187 | 
            +
                # Adds a duration in minutes to a date.
         | 
| 188 | 
            +
                #
         | 
| 189 | 
            +
                # The Boolean returned is always false.
         | 
| 190 | 
            +
                #
         | 
| 175 191 | 
             
                # @param [DateTime] start original date
         | 
| 176 | 
            -
                # @param [ | 
| 177 | 
            -
                # @ | 
| 178 | 
            -
                # @return [DateTime] the calculated date
         | 
| 179 | 
            -
                # @return [Fixnum] the number of minutes still to be added
         | 
| 180 | 
            -
                # @return [Boolean] Always false, this is the flag used for subtraction
         | 
| 192 | 
            +
                # @param [Integer] duration minutes to add
         | 
| 193 | 
            +
                # @return [DateTime, Integer, Boolean] the calculated date, remaining minutes and flag used for subtraction
         | 
| 181 194 | 
             
                #
         | 
| 182 195 | 
             
                def add(start,duration)
         | 
| 183 196 | 
             
                  # aim to calculate to the end of the day
         | 
| @@ -220,12 +233,12 @@ module Workpattern | |
| 220 233 | 
             
                end
         | 
| 221 234 |  | 
| 222 235 | 
             
                # Subtracts a duration in minutes from a date
         | 
| 236 | 
            +
                #
         | 
| 223 237 | 
             
                # @param [DateTime] start original date
         | 
| 224 | 
            -
                # @param [ | 
| 238 | 
            +
                # @param [Integer] duration minutes to subtract - always a negative
         | 
| 225 239 | 
             
                # @param [Boolean] midnight flag indicates the start date is midnight when true
         | 
| 226 | 
            -
                # @return [DateTime] the calculated date
         | 
| 227 | 
            -
                #  | 
| 228 | 
            -
                # @return [Boolean] When set to true indicates the time is midnight on the given date
         | 
| 240 | 
            +
                # @return [DateTime, Integer, Boolean] the calculated date, remaining number of minutes and 
         | 
| 241 | 
            +
                #     true if the time is midnight on the date
         | 
| 229 242 | 
             
                #
         | 
| 230 243 | 
             
                def subtract(start,duration,midnight=false)
         | 
| 231 244 |  | 
| @@ -286,10 +299,11 @@ module Workpattern | |
| 286 299 |  | 
| 287 300 | 
             
                # Supports calculating from midnight by updating the given duration depending on whether the
         | 
| 288 301 | 
             
                # last minute in the day is resting or working.  It then sets the time to this minute.
         | 
| 302 | 
            +
                #
         | 
| 289 303 | 
             
                # @param [DateTime] start is the date whose midnight is to be used as the start date
         | 
| 290 | 
            -
                # @param [ | 
| 291 | 
            -
                # @return [DateTime] the date with a time of 23:59
         | 
| 292 | 
            -
                # | 
| 304 | 
            +
                # @param [Integer] duration is the number of minutes to subtract
         | 
| 305 | 
            +
                # @return [DateTime, Integer] the date with a time of 23:59 and remaining duration
         | 
| 306 | 
            +
                #     adjusted according to whether 23:59 is resting or not
         | 
| 293 307 | 
             
                #
         | 
| 294 308 | 
             
                def minute_b4_midnight(start,duration)
         | 
| 295 309 | 
             
                  start -= start.hour * HOUR
         | 
| @@ -300,6 +314,7 @@ module Workpattern | |
| 300 314 | 
             
                end  
         | 
| 301 315 |  | 
| 302 316 | 
             
                # Calculates the date and time after the last working minute of the current date
         | 
| 317 | 
            +
                #
         | 
| 303 318 | 
             
                # @param [DateTime] start is the current date
         | 
| 304 319 | 
             
                # @return [DateTime] the new date
         | 
| 305 320 | 
             
                #
         | 
| @@ -314,11 +329,11 @@ module Workpattern | |
| 314 329 | 
             
                end
         | 
| 315 330 |  | 
| 316 331 | 
             
                # Calculates the difference between two dates that exist in this Week object.
         | 
| 332 | 
            +
                #
         | 
| 317 333 | 
             
                # @param [DateTime] start first date 
         | 
| 318 334 | 
             
                # @param [DateTime] finish last date
         | 
| 319 335 | 
             
                # @param [DateTime] finish_on the range to be used in this Week object.  
         | 
| 320 | 
            -
                # @return [DateTime] new date for rest of calculation  | 
| 321 | 
            -
                # @return [Fixnum] total number of minutes calculated thus far.
         | 
| 336 | 
            +
                # @return [DateTime, Integer] new date for rest of calculation and total number of minutes calculated thus far.
         | 
| 322 337 | 
             
                #
         | 
| 323 338 | 
             
                def diff_detail(start,finish,finish_on)
         | 
| 324 339 | 
             
                  duration, start=@values[start.wday].diff(start,finish)
         |