calc: Business Days

 
 8.5.3 Business Days
 -------------------
 
 Often time is measured in “business days” or “working days,” where
 weekends and holidays are skipped.  Calc’s normal date arithmetic
 functions use calendar days, so that subtracting two consecutive Mondays
 will yield a difference of 7 days.  By contrast, subtracting two
 consecutive Mondays would yield 5 business days (assuming two-day
 weekends and the absence of holidays).
 
    The ‘t +’ (‘calc-business-days-plus’) [‘badd’] and ‘t -’
 (‘calc-business-days-minus’) [‘bsub’] commands perform arithmetic using
 business days.  For ‘t +’, one argument must be a date form and the
 other must be a real number (positive or negative).  If the number is
 not an integer, then a certain amount of time is added as well as a
 number of days; for example, adding 0.5 business days to a time in
 Friday evening will produce a time in Monday morning.  It is also
 possible to add an HMS form; adding ‘12@ 0' 0"’ also adds half a
 business day.  For ‘t -’, the arguments are either a date form and a
 number or HMS form, or two date forms, in which case the result is the
 number of business days between the two dates.
 
    By default, Calc considers any day that is not a Saturday or Sunday
 to be a business day.  You can define any number of additional holidays
 by editing the variable ‘Holidays’.  (There is an ‘s H’ convenience
 command for editing this variable.)  Initially, ‘Holidays’ contains the
 vector ‘[sat, sun]’.  Entries in the ‘Holidays’ vector may be any of the
 following kinds of objects:
 
    • Date forms (pure dates, not date/time forms).  These specify
      particular days which are to be treated as holidays.
 
    • Intervals of date forms.  These specify a range of days, all of
      which are holidays (e.g., Christmas week).  SeeInterval Forms.
 
    • Nested vectors of date forms.  Each date form in the vector is
      considered to be a holiday.
 
    • Any Calc formula which evaluates to one of the above three things.
      If the formula involves the variable ‘y’, it stands for a yearly
      repeating holiday; ‘y’ will take on various year numbers like 1992.
      For example, ‘date(y, 12, 25)’ specifies Christmas day, and
      ‘newweek(date(y, 11, 7), 4) + 21’ specifies Thanksgiving (which is
      held on the fourth Thursday of November).  If the formula involves
      the variable ‘m’, that variable takes on month numbers from 1 to
      12: ‘date(y, m, 15)’ is a holiday that takes place on the 15th of
      every month.
 
    • A weekday name, such as ‘sat’ or ‘sun’.  This is really a variable
      whose name is a three-letter, lower-case day name.
 
    • An interval of year numbers (integers).  This specifies the span of
      years over which this holiday list is to be considered valid.  Any
      business-day arithmetic that goes outside this range will result in
      an error message.  Use this if you are including an explicit list
      of holidays, rather than a formula to generate them, and you want
      to make sure you don’t accidentally go beyond the last point where
      the holidays you entered are complete.  If there is no limiting
      interval in the ‘Holidays’ vector, the default ‘[1 .. 2737]’ is
      used.  (This is the absolute range of years for which Calc’s
      business-day algorithms will operate.)
 
    • An interval of HMS forms.  This specifies the span of hours that
      are to be considered one business day.  For example, if this range
      is ‘[9@ 0' 0" .. 17@ 0' 0"]’ (i.e., 9am to 5pm), then the business
      day is only eight hours long, so that ‘1.5 t +’ on ‘<4:00pm Fri Dec
      13, 1991>’ will add one business day and four business hours to
      produce ‘<12:00pm Tue Dec 17, 1991>’.  Likewise, ‘t -’ will now
      express differences in time as fractions of an eight-hour day.
      Times before 9am will be treated as 9am by business date
      arithmetic, and times at or after 5pm will be treated as 4:59:59pm.
      If there is no HMS interval in ‘Holidays’, the full 24-hour day
      ‘[0 0' 0" .. 24 0' 0"]’ is assumed.  (Regardless of the type of
      bounds you specify, the interval is treated as inclusive on the low
      end and exclusive on the high end, so that the work day goes from
      9am up to, but not including, 5pm.)
 
    If the ‘Holidays’ vector is empty, then ‘t +’ and ‘t -’ will act just
 like ‘+’ and ‘-’ because there will then be no difference between
 business days and calendar days.
 
    Calc expands the intervals and formulas you give into a complete list
 of holidays for internal use.  This is done mainly to make sure it can
 detect multiple holidays.  (For example, ‘<Jan 1, 1989>’ is both New
 Year’s Day and a Sunday, but Calc’s algorithms take care to count it
 only once when figuring the number of holidays between two dates.)
 
    Since the complete list of holidays for all the years from 1 to 2737
 would be huge, Calc actually computes only the part of the list between
 the smallest and largest years that have been involved in business-day
 calculations so far.  Normally, you won’t have to worry about this.
 Keep in mind, however, that if you do one calculation for 1992, and
 another for 1792, even if both involve only a small range of years, Calc
 will still work out all the holidays that fall in that 200-year span.
 
    If you add a (positive) number of days to a date form that falls on a
 weekend or holiday, the date form is treated as if it were the most
 recent business day.  (Thus adding one business day to a Friday,
 Saturday, or Sunday will all yield the following Monday.)  If you
 subtract a number of days from a weekend or holiday, the date is
 effectively on the following business day.  (So subtracting one business
 day from Saturday, Sunday, or Monday yields the preceding Friday.)  The
 difference between two dates one or both of which fall on holidays
 equals the number of actual business days between them.  These
 conventions are consistent in the sense that, if you add N business days
 to any date, the difference between the result and the original date
 will come out to N business days.  (It can’t be completely consistent
 though; a subtraction followed by an addition might come out a bit
 differently, since ‘t +’ is incapable of producing a date that falls on
 a weekend or holiday.)
 
    There is a ‘holiday’ function, not on any keys, that takes any date
 form and returns 1 if that date falls on a weekend or holiday, as
 defined in ‘Holidays’, or 0 if the date is a business day.