class TaskJuggler::WorkingHours

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.

Attributes

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

Public Class Methods

new(arg1 = nil, startDate = nil, endDate = nil, timeZone = nil) click to toggle source

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.

# File lib/taskjuggler/WorkingHours.rb, line 31
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

==(wh) click to toggle source

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

# File lib/taskjuggler/WorkingHours.rb, line 83
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
deep_clone() click to toggle source

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.

# File lib/taskjuggler/WorkingHours.rb, line 77
def deep_clone
  WorkingHours.new(self)
end
getWorkingHours(dayOfWeek) click to toggle source

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.

# File lib/taskjuggler/WorkingHours.rb, line 136
def getWorkingHours(dayOfWeek)
  @days[dayOfWeek]
end
onShift?(arg) click to toggle source

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

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

  if arg.is_a?(TjTime)
    @scoreboard.get(arg)
  else
    @scoreboard[arg]
  end
end
setWorkingHours(dayOfWeek, intervals) click to toggle source

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.

# File lib/taskjuggler/WorkingHours.rb, line 105
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
timeOff?(interval) click to toggle source

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

# File lib/taskjuggler/WorkingHours.rb, line 153
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
timezone=(zone) click to toggle source

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

# File lib/taskjuggler/WorkingHours.rb, line 128
def timezone=(zone)
  @scoreboard = nil
  @timezone = zone
end
to_s() click to toggle source

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

# File lib/taskjuggler/WorkingHours.rb, line 177
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
weeklyWorkingHours() click to toggle source

Return the number of working hours per week.

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