diff --git a/calendar/generate_calendar.php b/calendar/generate_calendar.php index 765b0a0..88ca397 100755 --- a/calendar/generate_calendar.php +++ b/calendar/generate_calendar.php @@ -20,45 +20,80 @@ be valid as a LaTeX macro name (i.e., no spaces, no digits, no punctuation). The components of each period specification are: - start_date: The date of the first day of the first week of the period. + start_date: The date of the first day of the first week of the period. - num_weeks: The total number of weeks in the period, /including/ any + num_weeks: The total number of weeks in the period, /including/ any breaks (e.g., 13 teaching weeks plus 1 week mid-semester break = 14 weeks). - break_week: A list of week numbers in which breaks from teaching occur. - The list should ideally be in ascending order, but the - script doesn't assume this and sorts the list anyway. The - week number of a break is relative to num_weeks, so if a - break week falls after the sixth then that week is week - number 7. The numbering of teaching weeks will skip the - break weeks regardless. If there are no breaks in the - period, then set this to an empty array. + break_weeks: A list of breaks that occur during the teaching period. + Each is specified by the start (break_start) and end + (break_end) week. If a break is only one week long, then + break_start and break_end should be equal. If there are no + breaks in the teaching period, include a single break + specification with both break_start and break_end set to zero. - Note that we aren't clever about coalescing contiguous - weeks. For example, if weeks 7 and 8 are indicated as break - weeks, a separate macro will be output for each week, not - one covering both weeks. It's probably technically feasible, - but not really worth the extra work :). + The list should ideally be in ascending order, but the + script doesn't assume this and sorts the list anyway. Weeks + are numbered by absolute calendar week number (i.e., week + 1 is the first calendar week of the year). The date of the + first Monday of the year is stored in $first_monday below + (everything is Monday-indexed). */ +$first_monday = new DateTime( "2012-01-02" ); + $periods = array( 'SummerSchool' => array( - 'start_date' => new DateTime( "2012-01-09" ), - 'num_weeks' => 6, - 'break_weeks' => array(), + 'first_week' => 2, + 'last_week' => 7, + 'break_weeks' => array( + array( + 'break_starts' => 0, + 'break_ends' => 0, + ), + ), ), 'SemesterOne' => array( - 'start_date' => new DateTime( "2012-02-27" ), - 'num_weeks' => 14, - 'break_weeks' => array( 7 ), + 'first_week' => 9, + 'last_week' => 22, + 'break_weeks' => array( + array( + 'break_starts' => 15, + 'break_ends' => 15, + ), + ), ), 'SemesterTwo' => array( - 'start_date' => new DateTime( "2012-07-09" ), - 'num_weeks' => 14, - 'break_weeks' => array( 8 ), + 'first_week' => 28, + 'last_week' => 41, + 'break_weeks' => array( + array( + 'break_starts' => 35, + 'break_ends' => 35, + ), + ), + ), + 'FullYear' => array( + 'first_week' => 9, + 'last_week' => 41, + 'break_weeks' => array( + array( + 'break_starts' => 23, + 'break_ends' => 27, + ), + array( + 'break_starts' => 15, + 'break_ends' => 15, + ), + array( + 'break_starts' => 35, + 'break_ends' => 35, + ), + ), ), ); + // A couple of handy date intervals: four days to the end of the current week, // and seven days to the start of next week. $plus_four_days = new DateInterval( 'P4D' ); @@ -68,50 +103,62 @@ foreach ( $periods as $period_name => $period_data ) { - $week_start = clone( $period_data['start_date'] ); + $week_start = clone( $first_monday ); + // Jump forward the correct number of weeks to the start of the teaching period. + $week_start->add( new DateInterval( sprintf( "P%dD", ( $period_data['first_week'] - 1 ) * 7 ) ) ); - // We need to adjust the teaching week number according to the number - // of break weeks that we've processed. $break_adjustment therefore - // effectively stores the count of break weeks processed so far. - $break_adjustment = 0; + $week_number = 0; + $num_breaks = 0; // Grab the first break week off the front of the list. sort( $period_data['break_weeks'] ); $break_week = array_shift( $period_data['break_weeks'] ); - for ( $week = 1; $week <= $period_data['num_weeks']; $week++ ) + for ( $week = $period_data['first_week']; $week <= $period_data['last_week']; $week++ ) { $week_end = clone( $week_start ); $week_end->add( $plus_four_days ); - // If the week start and end dates are in the same month, we only - // need to output the month name once. - $same_month = $week_start->format( 'n' ) == $week_end->format( 'n' ); - // Handle break weeks. - if ( $week == $break_week ) + if ( ( $week >= $break_week['break_starts'] ) && ( $week <= $break_week['break_ends'] ) ) { - // Increment this first before doing anything else, because we use - // it to generate a macro name for this break, and we want the - // macro numbering to start from one, not zero. - $break_adjustment++; + if ( $week == $break_week['break_starts'] ) + { + $num_breaks++; + + // Work out the end date of the break. + $break_end = clone( $week_start ); + // Note: +4 days to get to Friday. + $break_end->add( + new DateInterval( + sprintf( "P%dD", ( ( $break_week['break_ends'] - $break_week['break_starts'] ) * 7 ) + 4 ) + ) + ); + + // Output macro for inclusion in paper calendar. + printf( "\\newcommand{\\%sBreak%s}{%s--%s}\n", + $period_name, + ucfirst( $numwords->toWords( $num_breaks ) ), + // If the week start and end dates are in the same month, we only + // need to output the month name once. + ( $week_start->format( 'n' ) == $break_end->format( 'n' ) ) ? $week_start->format( 'j' ) : $week_start->format( 'j M' ), + $break_end->format( 'j M' ) + ); + } // if current week == first week of break - // Output macro for inclusion in paper calendar. - printf( "\\newcommand{\\%sBreak%s}{%s--%s}\n", - $period_name, - ucfirst( $numwords->toWords( $break_adjustment ) ), - ( $same_month ) ? $week_start->format( 'j' ) : $week_start->format( 'j M' ), - $week_end->format( 'j M' ) - ); - - // Grab the next break week off the front of the list. - $break_week = array_shift( $period_data['break_weeks'] ); - } // if break week + if ( $week == $break_week['break_ends'] ) + { + // Grab the next break week off the front of the list. + $break_week = array_shift( $period_data['break_weeks'] ); + } // if current week == last week of break + } // if current week is a break week else { - $week_number = $week - $break_adjustment; + $week_number++; - if( $same_month ) + // If the week start and end dates are in the same month, we only + // need to output the month name once. + if ( $week_start->format( 'n' ) == $week_end->format( 'n' ) ) { // Output macro for inclusion in paper calendar. printf( "\\newcommand{\\%sWeek%s}{%s--%s \\\\ %s}\n",