Class TaskJuggler::WorkingHours
In: lib/taskjuggler/WorkingHours.rb
Parent: Object

Class to store the working hours for each day of the week. The working hours are stored as Arrays of Fixnum intervals for each day of the week. A day off is modelled as empty Array for that week day. The start end end times of each working period are stored as seconds after midnight.

Methods

Attributes

days  [R] 
endDate  [R] 
scoreboard  [R] 
slotDuration  [R] 
startDate  [R] 
timezone  [R] 

Public Class methods

Create a new WorkingHours object. The method accepts a reference to an existing WorkingHours object in wh. When it‘s present, the new object will be a deep copy of the given object. The Scoreboard object is not deep copied. It will be copied on write.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 32
    def initialize(arg1 = nil, startDate = nil, endDate = nil, timeZone = nil)
      # One entry for every day of the week. Sunday === 0.
      @days = Array.new(7, [])
      @scoreboard = nil

      if arg1.is_a?(WorkingHours)
        # Create a copy of the passed WorkingHours object.
        wh = arg1
        @timezone = wh.timezone
        7.times do |day|
          hours = []
          wh.days[day].each do |hrs|
            hours << hrs.dup
          end
          setWorkingHours(day, hours)
        end
        @startDate = wh.startDate
        @endDate = wh.endDate
        @slotDuration = wh.slotDuration
        # Make sure the copied scoreboard has been created, so we can share it
        # copy-on-write.
        wh.onShift?(0)
        @scoreboard = wh.scoreboard
      else
        slotDuration = arg1
        if arg1.nil? || startDate.nil? || endDate.nil?
          raise "You must supply values for slotDuration, start and end dates"
        end
        @startDate = startDate
        @endDate = endDate
        @slotDuration = slotDuration

        # Create a new object with default working hours.
        @timezone = timeZone
        # Set the default working hours. Monday to Friday 9am - 5pm.
        # Saturday and Sunday are days off.
        1.upto(5) do |day|
          @days[day] = [ [ 9 * 60 * 60, 17 * 60 * 60 ] ]
        end
      end
    end

Public Instance methods

Return true of the given WorkingHours object wh is identical to this object.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 84
    def ==(wh)
      return false if wh.nil? || @timezone != wh.timezone ||
             @startDate != wh.startDate ||
             @endDate != wh.endDate ||
             @slotDuration != wh.slotDuration

      7.times do |d|
        return false if @days[d].length != wh.days[d].length
        # Check all working hour intervals
        @days[d].length.times do |i|
          return false if @days[d][i][0] != wh.days[d][i][0] ||
                          @days[d][i][1] != wh.days[d][i][1]
        end
      end
      true
    end

Since we want to share the scoreboard among instances with identical working hours, we need to prevent the scoreboard from being deep cloned. Calling the constructor with self in a re-defined deep_clone method will do just that.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 78
    def deep_clone
      WorkingHours.new(self)
    end

Return the working hour intervals for a given day of the week. dayOfWeek must 0 for Sunday, 1 for Monday and so on. The result is an Array that contains Arrays of 2 Fixnums.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 137
    def getWorkingHours(dayOfWeek)
      @days[dayOfWeek]
    end

Return true if arg is within the defined working hours. arg can be a TjTime object or a global scoreboard index.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 143
    def onShift?(arg)
      initScoreboard unless @scoreboard

      if arg.is_a?(TjTime)
        @scoreboard.get(arg)
      else
        @scoreboard[arg]
      end
    end

Set the working hours for a given week day. dayOfWeek must be 0 for Sunday, 1 for Monday and so on. intervals must be an Array that contains an Array with 2 Fixnums for each working period. Each value specifies the time of day as minutes after midnight. The first value is the start time of the interval, the second the end time.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 106
    def setWorkingHours(dayOfWeek, intervals)
      # Changing the working hours requires the score board to be regenerated.
      @scoreboard = nil

      # Legal values range from 0 Sunday to 6 Saturday.
      if dayOfWeek < 0 || dayOfWeek > 6
        raise "dayOfWeek out of range: #{dayOfWeek}"
      end
      intervals.each do |iv|
        if iv[0] < 0 || iv[0] > 24 * 60 * 60 ||
           iv[1] < 0 || iv[1] > 24 * 60 * 60
          raise "Time interval has illegal values: " +
                "#{time_to_s(iv[0])} - #{time_to_s(iv[1])}"
        end
        if iv[0] >= iv[1]
          raise "Interval end time must be larger than start time"
        end
      end
      @days[dayOfWeek] = intervals
    end

Return true only if all slots in the interval are offhour slots.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 154
    def timeOff?(interval)
      initScoreboard unless @scoreboard

      startIdx = @scoreboard.dateToIdx(interval.start)
      endIdx = @scoreboard.dateToIdx(interval.end)

      startIdx.upto(endIdx - 1) do |i|
        return false if @scoreboard[i]
      end
      true
    end

Set the time zone zone for the working hours. This will reset the @scoreboard.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 129
    def timezone=(zone)
      @scoreboard = nil
      @timezone = zone
    end

Returns the time interval settings for each day in a human readable form.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 178
    def to_s
      dayNames = %w( Sun Mon Tue Wed Thu Fri Sat )
      str = ''
      7.times do |day|
        str += "#{dayNames[day]}: "
        if @days[day].empty?
          str += "off"
          str += "\n" if day < 6
          next
        end
        first = true
        @days[day].each do |iv|
          if first
            first = false
          else
            str += ', '
          end
          str += "#{time_to_s(iv[0])} - #{time_to_s(iv[0])}"
        end
        str += "\n" if day < 6
      end
      str
    end

Return the number of working hours per week.

[Source]

# File lib/taskjuggler/WorkingHours.rb, line 167
    def weeklyWorkingHours
      seconds = 0
      @days.each do |day|
        day.each do |from, to|
           seconds += (to - from)
        end
      end
      seconds / (60 * 60)
    end

[Validate]