Date Time Subsystem Analysis
============================

Audience: Developers
Author:   James Hunt, Lead Developer

Abstract:
	This document includes some detailed use cases
and scenarios related to the components of the
date/time subsystem, covering various edge cases
as well as normal usage.  This document can be
used as a springboard for testing the subsystem,
and will be updated with new use cases as well as
re-evalutations of existing scenarios whenever
major changes are made to the subsystem.



--------------------------------------------
    pathos_datetime_recurringWeeklyDates    
--------------------------------------------
o Finding the Starting Date:

  Starting date's weekday is after the last weekday
  in the recurrence rotation.  (Start on a Saturday for
  a MWF rotation)
  
   Set the day counter ($counter) to 0, so that we start
    on the first day of the rotation
	
   Set the start date to one the next day that is the first
    weekday of the rotation.  Currently this is done by:
	
	$start += (SECONDS_PER_DAY) * (7 - CURRENT_WEEKDAY + FIRST_WEEKDAY)
	
	***********
	* Use Case: MWF Rotation, Starting on a Saturday
	
	 So, if CURRENT_WEEKDAY is Saturday (integer value 6), and
	 the rotation is MWF, Monday (1) is the FIRST_WEEKDAY.
	
	 $start = $start + 86400 * (7 - 6 + 1) = $start + 86400 * (2)
	
	 We would be adding 2 days to the $start timestamp, landing us
	 at the next monday.
	
	***********
	* Use Case: Su Rotation, Starting on a Monday
	
	 If the CURRENT_WEEKDAY is a Monday (1) and the rotation is Su,
	 Sunday (0) is the FIRST_WEEKDAY
	
	 $start = $start + 86400 * (7 - 1 + 0) = $start + 86400 * (6)
	
	 This will add 6 days to Monday (1) resulting in a Sunday (7)

  Starting date's weekday is before the last weekday
  in the recurrence rotation. (Start on a Sunday for
  a MWF rotation)

	
	Do nothing, as start date is already correct.
	

  Starting date's weekday is before the last weekday
  in the recurrence rotation. (Start on a Sunday for
  a MWF rotation)
  
	Set the start date to the next day in the rotation that is after
	 the current day.
	 

o Finding Dates falling in Recurrence Range
  
  A do...while loop finds all of the events that match the recurrence
  criteria within the range of recurrence.
  
  During the iteration, we moved off of the last weekday and back onto
  the first weekday in the rotation.
  
   Reset the counter to 0, so we pick up the proper weekday on the next
    iteration
   Grab the difference in days between the last weekday in the rotation
    and the first day in the rotation. Currently this is done as:
	
	$diff = 7 + FIRST_WEEKDAY - LAST_WEEKDAY
	
   Increment the current date.  Currently this is done as:
   
    $curdate += 7 * (SECONDS_PER_DAY) * (WEEKLY_FREQUENCY-1) + (SECONDS_PER_DAY * DIFFERENCE)
	
	***********
	* Use Case: MF Rotation, Moving from Friday to Monday, every 1 week
	
	 Frequency (WEEKLY_FREQ) is 1
	 The difference (DIFFERENCE) between Friday (5) and Monday (1) is:
	  $diff = 7 + 1 - 5 = 3
	 
	 Increment $curdate using provided formula:
	 
	  $curdate = $curdate + 7 * 86400 * (WEEKLY_FREQ-1) + (86400 * 3)
	  
	  The second term drops out, because WEEKLY_FREQ-1 = 0
	  
	  $curdate = $curdate + 0 + 86400 * 3
	  
	  So we are adding three days to the current date, and three days
	  after a friday is (5 + 3) is 8 (subtract 7 for the week), or
	  weekday 1.  This is a monday.
	  
	***********
	* Use Case: MTh Rotation, Moving from Thursday to Monday, every 1 week
	
	 Frequency (WEEKLY_FREQ) is 1
	 The difference (DIFFERENCE) between Thursday (4) and Monday (1) is:
	  $diff = 7 + 1 - 4 = 4
	 
	 Increment $curdate using the provided formula:
	
	  $curdate = $curdate + 7 * 86400 * (WEEKLY_FREQ-1) + (86400 * 4)
	  
	  The second term drops out, because WEEKLY_FREQ-1 = 0
	  
	  $curdate = $curdate + 0 + 86400 * 4
	  
	  So we are adding four days to the current date, and four days after
	  a thursday (4 + 4) is 8 (Subtract 7 for the week), or weekday 1.
	  This is a monday.
	  
	-------------------------------------------------------
	  Formulaic Discussion of Day Difference Calculations
	-------------------------------------------------------
	
	What follows is a set of equations to figure out the day
	difference between two days, when wrapping around one week to
	the next.  For purposes of brevity, any weekdays between the first
	and last in the rotation are ignored, since they have no effect on
	the dayspan between first weekday and last weekday (a MF rotation is
	identical to a MTuWThF rotation when wrapping, both go Friday to
	Monday)
	
	MSa Rotation:
		Sa - M = 6 - 1 = 5
		6 + X = 7 + 1
		  Solving for X gives X = 7 + 1 - 6
		  X = 2
	MF Rotation:
		F - M = 5 - 1 = 4
		5 + X = 7 + 1
		  Solving for X gives X = 7 + 1 - 5
		  X = 3
	MTh Rotation:
		Th - M = 4 - 1 = 3
		4 + X = 7 + 1
		  Solving for X gives X = 7 + 1 - 4
		  X = 4
	MW Rotation:
		W - M = 3 - 1 = 2
		3 + X = 7 + 1
		  Solving for X gives X = 7 + 1 - 3
		  X = 5
	MTu Rotation:
		Tu - M = 2 - 1 = 1
		2 + X = 7 + 1
		  Solving for X gives X = 7 + 1 - 2
		  X = 6
	TuSa Rotation:
		Sa - Tu = 6 - 2 = 3
		6 + X = 7 + 2
		  Solving for X gives X = 7 + 2 - 6
		  X = 3
	
	X = WEEKLY + FIRST_WDAY - LAST_WDAY
	X = number of days to add to the last day to get to the first day
	
	
--------------------------------------------
    pathos_datetime_recurringMonthlyDates    
--------------------------------------------

o Finding the start date

  We only need to do special stuff if we have chosen to recur on the
  weekday.  In that case, we need to find what weekday we are, and what
  week offset (i.e. the 3rd Thursday).  Otherwise, the passed start date
  works just fine.
  
  WEEKOFFSET = floor ( MONTH_DATE / 7 )
  
  Scenarios for Week Offset / Weekday Calculations:
  
   January 13, 2005 (Thursday) - Second thursday of the month
   - Already know the weekday (thursday, 4)
   
   WEEKOFFSET = ceil ( 13 / 7 ) = ceil ( 1.857... ) = 2
   
   January 15, 2005 (Saturday) - Third saturday of the month
   - Already know the weekday (saturday, 6)
   
   WEEKOFFSET = ceil ( 15 / 7 ) = ceil ( 2.142... ) = 3
   
   January 30, 2005 (Sunday) - Fifth sunday of the month
   - Already know the weekday (sunday, 0)
   
   WEEKOFFSET = ceil ( 30 / 7 ) = ceil ( 4.285... ) = 5

o Finding the next 'by day' date in a series

  What information we have to work with:
   - The week offset (the nth weekday of the month)
   - The start date info of the next month in the cycle
   - The weekday we are shooting for.
   
  There are a few different situations.  For all, consider Jan 2005:
  
				January 2005
			Su Mo Tu We Th Fr Sa 
							   1
			 2  3  4  5  6  7  8
			 9 10 11 12 13 14 15
			16 17 18 19 20 21 22
			23 24 25 26 27 28 29
			30 31

   And also consider Feb 2005:

				February 2005
			Su Mo Tu We Th Fr Sa 
				   1  2  3  4  5
			 6  7  8  9 10 11 12
			13 14 15 16 17 18 19
			20 21 22 23 24 25 26
			27 28
  
   1. Month start weekday is before target weekday.
     Get the difference between starting weekday and target
	 weekday, add then, then add one less than the week offset
	 multiplied by 7, then add 1, for the start date (the 1st)
	 
	 DATE = TARGET_WDAY - START_WDAY + ( 7 * ( OFFSET - 1 ) ) + 1
	 
      February:
	  Month started on a tuesday (1st), and we want the 3rd friday (18th).
	  
	  DATE = F - Tu + ( 7 * 2 ) + 1 = 5 - 2 + 1 + ( 14 ) = 4 + 14 = 18
	  
	  February:
	  Month started on a tuesday (1st), and we want the 2nd wed (9th).
	  
	  DATE = W - Tu + ( 7 * 1 ) + 1 = 3 - 2 + 1 + ( 7 ) = 2 + 9
   
   2. Month start weekday is the target weekday.
      In the event that the TARGET_WDAY and START_WDAY values in the
	  equation for situation 1. above, the first term drops out:
	  
	  DATE = 0 - 0 + ( 7 * ( OFFSET - 1 ) ) + 1
	  
	  February:
	  Month started on a tuesday (1), and we want the 2nd tues (8th).
	  
	  DATE = Tu - Tu + ( 7 * 1 ) + 1 = ( 7 ) + 1 = 8
	  
	  January:
	  Month started on a Saturday (1st), and we want the 4th saturday (22nd)
	  
	  DATE = Sa - Sa + ( 7 * 3 ) + 1 = ( 21 ) + 1 = 22
	  
	  continue on to Feb.
	  Mont started on a tuesday (1), and we want the 4th staurday (26)
	  
	  DATE = Sa - Tu + ( 7 * 3 ) + 1 = 6 - 2 + 14 + 1 = 26
   
   
   3. Month start weekday is after the target weekday.
      In the event that the TARGET_WDAY is numerically less than the
	  START_WDAY value, then in the equation for situation 1, the first term
	  (TARGET_WDAY - START_WDAY) is negative.  This may or may not work.
	  
	  January:
	  Month started on a Saturday (1st), and we want the 2nd monday (10th)
	  
	  DATE = M - Sa + ( 7 * 1 ) + 1 = 1 - 6 + 1 + ( 7 * 1 ) = -4 + 7 = 3
	  
	  January:
	  Month started on a Saturday (1st), and we want the 3rd friday (21st)
	  
	  DATE = F - Sa + ( 7 * 2 ) + 1 = 5 - 6 + 1 + ( 14 ) = 14
	  
	  February:
	  Month started on a tuesday (1st), and we want the 1st monday (7)
	  
	  DATE = M - Tu + ( 7 * 0 ) + 1 = 1 - 2 + 1 + ( 0 ) = 0
	  
	  February:
	  Month started on a tuesday (1st), and we want the 2nd sunday (13)
	  
	  DATE = S - Tu + ( 7 * 1 ) + 1 = 0 - 2 + 1 ( 7 ) = 6
	  
	  Each of these dates is a week early.  So, for situation 3, we can ignore
	  the -1 modification to the OFFSET, and always get the correct date.