Newer
Older
Handbook / calendar / generate_calendar.php
  1. <?php
  2.  
  3. /*
  4. This script generates a LaTeX include file that contains macros specifying
  5. the date ranges for every week of the three main teaching periods through
  6. the year (i.e., summer school, first semester, second semester). Simply set
  7. the configuration as outlined below and run the script, saving the output
  8. in a suitable location, ideally only once for all papers. A good spot would
  9. be somewhere in the TeX search path.
  10. */
  11.  
  12. // LaTeX macro names can't include numbers, so we have to convert them to words.
  13. require 'Numbers/Words.php';
  14.  
  15. /*
  16. Teaching period configuration. It's easily extensible to a new teaching
  17. period simply by adding a new specification for that period. The key should
  18. be valid as a LaTeX macro name (i.e., no spaces, no digits, no punctuation).
  19. The components of each period specification are:
  20. first_week: The academic week number of the first week of the period.
  21. last_week: The academic week number of the last week of the period.
  22. break_weeks: A list of breaks that occur during the teaching period.
  23. Each is specified by the start (break_start) and end
  24. (break_end) week. If a break is only one week long, then
  25. break_start and break_end should be equal. If there are no
  26. breaks in the teaching period, include a single break
  27. specification with both break_start and break_end set to zero.
  28. The list should ideally be in ascending order, but the
  29. script doesn't assume this and sorts the list anyway. Weeks
  30. are numbered by academic week number (i.e., week 1 is the
  31. first academic week of the year). The date of the first
  32. Monday of the year is stored in $first_monday below
  33. (everything is Monday-indexed). Note that academic week is
  34. normally the same as absolute calendar week.
  35.  
  36. Example:
  37. $year = 2013;
  38. $first_monday = new DateTime( "2012-12-31" );
  39. $periods = array(
  40. 'SummerSchool' => array(
  41. 'first_week' => 2,
  42. 'last_week' => 7,
  43. 'break_weeks' => array(
  44. array(
  45. 'break_starts' => 0,
  46. 'break_ends' => 0,
  47. ),
  48. ),
  49. ),
  50. 'SemesterOne' => array(
  51. 'first_week' => 9,
  52. 'last_week' => 22,
  53. 'break_weeks' => array(
  54. array(
  55. 'break_starts' => 14,
  56. 'break_ends' => 14,
  57. ),
  58. ),
  59. ),
  60. 'SemesterTwo' => array(
  61. 'first_week' => 28,
  62. 'last_week' => 41,
  63. 'break_weeks' => array(
  64. array(
  65. 'break_starts' => 35,
  66. 'break_ends' => 35,
  67. ),
  68. ),
  69. ),
  70. 'FullYear' => array(
  71. 'first_week' => 9,
  72. 'last_week' => 41,
  73. 'break_weeks' => array(
  74. array(
  75. 'break_starts' => 23,
  76. 'break_ends' => 27,
  77. ),
  78. array(
  79. 'break_starts' => 15,
  80. 'break_ends' => 15,
  81. ),
  82. array(
  83. 'break_starts' => 35,
  84. 'break_ends' => 35,
  85. ),
  86. ),
  87. ),
  88. );
  89. */
  90. require 'calendar_config.php';
  91.  
  92.  
  93. // A couple of handy date intervals: four days to the end of the current week,
  94. // and seven days to the start of next week.
  95. $plus_four_days = new DateInterval( 'P4D' );
  96. $plus_seven_days = new DateInterval( 'P7D' );
  97.  
  98. $numwords = new Numbers_Words();
  99.  
  100. printf( "%% Teaching calendar dates for %s.\n", $year );
  101.  
  102. foreach ( $periods as $period_name => $period_data )
  103. {
  104. $week_start = clone( $first_monday );
  105. // Jump forward the correct number of weeks to the start of the teaching period.
  106. $week_start->add( new DateInterval( sprintf( "P%dD", ( $period_data['first_week'] - 1 ) * 7 ) ) );
  107. $week_number = 0;
  108. $num_breaks = 0;
  109. // Grab the first break week off the front of the list.
  110. sort( $period_data['break_weeks'] );
  111. $break_week = array_shift( $period_data['break_weeks'] );
  112. for ( $week = $period_data['first_week']; $week <= $period_data['last_week']; $week++ )
  113. {
  114. $week_end = clone( $week_start );
  115. $week_end->add( $plus_four_days );
  116. // Handle break weeks.
  117. if ( ( $week >= $break_week['break_starts'] ) && ( $week <= $break_week['break_ends'] ) )
  118. {
  119. if ( $week == $break_week['break_starts'] )
  120. {
  121. $num_breaks++;
  122. // Work out the end date of the break.
  123. $break_end = clone( $week_start );
  124. // Note: +4 days to get to Friday.
  125. $break_end->add(
  126. new DateInterval(
  127. sprintf( "P%dD", ( ( $break_week['break_ends'] - $break_week['break_starts'] ) * 7 ) + 4 )
  128. )
  129. );
  130. // Output macro for inclusion in paper calendar.
  131. printf( "\\newcommand{\\%sBreak%s}{%s--%s}\n",
  132. $period_name,
  133. str_replace( "-", "", ucfirst( $numwords->toWords( $num_breaks ) ) ),
  134. // If the week start and end dates are in the same month, we only
  135. // need to output the month name once.
  136. ( $week_start->format( 'n' ) == $break_end->format( 'n' ) ) ? $week_start->format( 'j' ) : $week_start->format( 'j M' ),
  137. $break_end->format( 'j M' )
  138. );
  139. } // if current week == first week of break
  140. if ( $week == $break_week['break_ends'] )
  141. {
  142. // Grab the next break week off the front of the list.
  143. $break_week = array_shift( $period_data['break_weeks'] );
  144. } // if current week == last week of break
  145. } // if current week is a break week
  146. else
  147. {
  148. $week_number++;
  149. // If the week start and end dates are in the same month, we only
  150. // need to output the month name once.
  151. if ( $week_start->format( 'n' ) == $week_end->format( 'n' ) )
  152. {
  153. // Output macro for inclusion in paper calendar.
  154. printf( "\\newcommand{\\%sWeek%s}{%s--%s \\\\ %s}\n",
  155. $period_name,
  156. str_replace( "-", "", ucfirst( $numwords->toWords( $week_number ) ) ),
  157. $week_start->format( 'j' ),
  158. $week_end->format( 'j' ),
  159. $week_end->format( 'M' )
  160. );
  161. } // if same month
  162. else
  163. {
  164. // Output macro for inclusion in paper calendar.
  165. printf( "\\newcommand{\\%sWeek%s}{%s \\\\ --%s}\n",
  166. $period_name,
  167. str_replace( "-", "", ucfirst( $numwords->toWords( $week_number ) ) ),
  168. $week_start->format( 'j M' ),
  169. $week_end->format( 'j M' )
  170. );
  171. } // else different months
  172. } // else normal teaching week
  173. $week_start->add( $plus_seven_days );
  174. } // for each week
  175. } // foreach teaching period
  176.  
  177. ?>