/* * This class implements all the methods necessary for the U of A Limited * Calendric System. *
* This calendric system has 3 epocs: * January 1, 0001 00:00:00 - August 21, 2000 06:59:59 -> ADGregorian Calendar * August 21, 2000 07:00:00 - August 11, 2004 20:59:59 -> U of A Calendar * August 11, 2004 21:00:00 - extentOf(ADGregorian Calendar) -> ADGregorian Calendar *
* This class has the two methods castGregHourToUofAHour() and * castUofAHourToGregHour(). With these two methods, the lattice will be able * to do calculations between the two calendars in this calendric system. * * Last Updated: 2003/2/28 by Jessica Miller */ public class UofALimitedCalendricSystem { /******************************************************************************/ /* Constants */ /******************************************************************************/ private static final long NUM_MINS_IN_DAY = 60; private static final long NUM_HOURS_IN_GREG_DAY = 24; private static final long NUM_HOURS_IN_UOFA_DAY = 14; private static final long NUM_DAYS_IN_GREG_WEEK = 7; private static final long NUM_DAYS_IN_UOFA_WEEK = 5; private static final long NUM_HOURS_IN_GREG_WEEK = NUM_HOURS_IN_GREG_DAY * NUM_DAYS_IN_GREG_WEEK; private static final long NUM_HOURS_IN_UOFA_WEEK = NUM_HOURS_IN_UOFA_DAY * NUM_DAYS_IN_UOFA_WEEK; private static final long NUM_INVALID_GREG_HOURS_IN_UOFA_WEEK = 98; private static final long NUM_INVALID_GREG_HOURS_IN_UOFA_DAY = 10; private static final long GREG_HOUR_ANCHOR = 17528455; // i.e. 9pm Friday - 7am Monday is weekend and hours in between are invalid private static final long FIRST_WKEND_GREG_HOUR = 110; // i.e. if first hour (0th hour) of day is 7am, the 14th hour (or 9pm is the // first invalid Gregorian calendar in the uofa day) private static final long FIRST_INVALID_GREG_HOUR_IN_UOFA_DAY = 14; private static final int INVALID_ARG = -1; private static final int BREAK_START = 0; private static final int BREAK_END = 1; // the first row is the row that has the hour of start of a break; the second // row is the hour of the end of the break; therefore, if there is a // Gregorian hour between (and including) these hours, it is an invalid // academic hour private static final long[][] HOURS_OF_BREAKS = { { // start dates (first hour) of August breaks ADGregorianCalendar.sumMinutes(2001, 8, 8, 21, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2002, 8, 8, 21, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2003, 8, 13, 21, 0) / NUM_MINS_IN_DAY }, { // end dates (last hour) of August breaks ADGregorianCalendar.sumMinutes(2001, 8, 20, 6, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2002, 8, 26, 6, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2003, 8, 25, 6, 0) / NUM_MINS_IN_DAY } }; private static final int GREG_HOUR_AFTER_BREAK = 0; private static final int GREG_HOURS_IN_BREAK = 1; private static final int UOFA_HOUR_AFTER_BREAK = 0; private static final int UOFA_HOURS_IN_BREAK = 1; private static final int UOFA_DAYS_NOT_COUNTED = 2; // this array's first row is the first valid Gregorian hour after a break; the // second row is the number of uofa hours that occurred during the break private static final long[][] UOFA_HOURS_IN_BREAKS = { { // first Gregorian hour after August breaks ADGregorianCalendar.sumMinutes(2001, 8, 20, 7, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2002, 8, 26, 7, 0) / NUM_MINS_IN_DAY, ADGregorianCalendar.sumMinutes(2003, 8, 25, 7, 0) / NUM_MINS_IN_DAY }, { // number of uofa calendar hours that occurred during the break 98, // # invalid uofa hours between August 8, 2001 9pm - August 20, 2001 7am 154, // # invalid uofa hours between August 8, 2002 9pm - August 26, 2002 7am 98 // # invalid uofa hours between August 13, 2003 9pm - August 25, 2003 7am } }; // this array's first row is the first valid uofa hour after a break; the // second row is the number of Gregorian hours that occurred during the break private static final long[][] GREG_HOURS_IN_BREAKS = { { // first UofA hour after August breaks castGregHourToUofAHour(ADGregorianCalendar.sumMinutes(2001, 8, 20, 7, 0) / NUM_MINS_IN_DAY), castGregHourToUofAHour(ADGregorianCalendar.sumMinutes(2002, 8, 26, 7, 0) / NUM_MINS_IN_DAY), castGregHourToUofAHour(ADGregorianCalendar.sumMinutes(2003, 8, 25, 7, 0) / NUM_MINS_IN_DAY) }, { // number of Gregorian calendar hours that occurred during the break 9 * 24, // Gregorian hours not counted between August 11 - 19, 2001 16 * 24, // Gregorian hours not counted between August 10 - 25, 2002 9 * 24 // Gregorian hours not counted between August 16 - 24, 2003 }, { 2, 1, 2 } }; /***************************************************************************/ /* Helper methods */ /***************************************************************************/ /* * Returns whether or not the given Gregorian hour is a Gregorian hour that * takes place during a break during the academic year. The breaks of * academic years typically take place during the 2nd/3rd week of August. * * @param gregHour number of Gregorian hour granules * @return whether or not the hour granule occurs during a break */ private static boolean isInBreak(long gregHour) { for (int i = 0; i < HOURS_OF_BREAKS[BREAK_START].length; i++) { if (HOURS_OF_BREAKS[BREAK_START][i] <= gregHour && gregHour <= HOURS_OF_BREAKS[BREAK_END][i]) return true; } return false; } /* * Returns how many uofa calendar hours have occurred during all breaks up * to this Gregorian hour. * * @param gregHour number of Gregorian hour granules * @return number of uofa calendar hours that have occurred in * breaks */ private static long numUofABreakHours(long gregHour) { long uofaHoursInBreaks = 0; for (int i = 0; i < UOFA_HOURS_IN_BREAKS[GREG_HOUR_AFTER_BREAK].length; i++) { if (UOFA_HOURS_IN_BREAKS[GREG_HOUR_AFTER_BREAK][i] <= gregHour) uofaHoursInBreaks += UOFA_HOURS_IN_BREAKS[UOFA_HOURS_IN_BREAK][i]; else break; } return uofaHoursInBreaks; } /***************************************************************************/ /* Methods that will be used for the irregular mappings in this calendar */ /***************************************************************************/ public static long castGregHourToUofAHour(Long gregHourL){ return castGregHourToUofAHour(gregHourL.longValue()); } /* * Covert the given amount of Gregorian hours to UofA hours using the * cast operation. *
* Algorithm: (1) check if given Gregorian hour is a valid UofA hour by * checking if it occurs during * - a break, * - a weekend, * - or, invalid hours of the day (between 9p - 7a) * (2) if it is a valid uofa hour, calculate which uofa hour the * Gregorian calendar corresponds to by subtracting the * following from the Gregorian hour * - the Gregorian anchor * - the number of hours in every Gregorian week that aren't * in a UofA week * - the number of hours in the remainding Gregorian days that * aren't in a UofA day * - the number of Gregorian hours in the breaks * * @param gregHour number of Gregorian hour granules to cast into UofA hour * granularity * @return number of UofA hour granules */ public static long castGregHourToUofAHour(long gregHour) { long hourInWeek, hourInDay, weeks, days; if (isInBreak(gregHour)) return INVALID_ARG; hourInWeek = (gregHour - GREG_HOUR_ANCHOR) % NUM_HOURS_IN_GREG_WEEK; if (hourInWeek >= FIRST_WKEND_GREG_HOUR) return INVALID_ARG; hourInDay = hourInWeek % NUM_HOURS_IN_GREG_DAY; if (hourInDay >= FIRST_INVALID_GREG_HOUR_IN_UOFA_DAY) return INVALID_ARG; weeks = (gregHour - GREG_HOUR_ANCHOR) / NUM_HOURS_IN_GREG_WEEK; days = hourInWeek / NUM_HOURS_IN_GREG_DAY; return gregHour - GREG_HOUR_ANCHOR - weeks * NUM_INVALID_GREG_HOURS_IN_UOFA_WEEK - days * NUM_INVALID_GREG_HOURS_IN_UOFA_DAY - numUofABreakHours(gregHour); } public static long castUofAHourToGregHour(Long uofaHourL){ return castUofAHourToGregHour(uofaHourL.longValue()); } /* * Covert the given amount of UofA hours to Gregorian hours using the * cast operation. *
* Algorithm: (1) figure out how many irregular UofA weeks there are (ones * that don't count all five days), how many UofA days aren't * counted in these weeks, and how many Gregorian hours are in * the breaks * (2) get the number of full UofA weeks have been completed during * the uofaHour * (3) get the number of remainding days that have been completed * this uofaHour * (4) calculate the number of Gregorian hours that have passed in * every irregular week by * - counting the number of Gregorian hours that have occurred * in non-UofA counted days in this week * - plus the number of Gregorian hours that have occurred in * UofA days (that wouldn't be counted by UofA hours) * - plus the number of Gregorian hours that pass during the * breaks * (5) calculate the total number of Gregorian hours to this UofA * hour by adding * - number of hours in the UofA hour * - number of hours in the Gregorian anchor * - number of Gregorian hours that aren't counted in the UofA * weeks * - number of Gregorian hours that aren't counted in the * remaining UofA days * - number of Gregorian hours that aren't counted in the * irregular UofA weeks and breaks * * @param uofaHour number of UofA hour granules to cast into Gregorian hour * granularity * @return number of Gregorian hour granules */ public static long castUofAHourToGregHour(long uofaHour) { long weeks, days; long irregularUofAWeeks = 0, uofaDaysNotCounted = 0, gregBreakHours = 0; long gregHoursInIrregWeeks = 0, uofaHoursNotCounted = 0; for (int i = 0; i < GREG_HOURS_IN_BREAKS[UOFA_HOUR_AFTER_BREAK].length; i++) { if (GREG_HOURS_IN_BREAKS[UOFA_HOUR_AFTER_BREAK][i] <= uofaHour) { irregularUofAWeeks++; gregBreakHours += GREG_HOURS_IN_BREAKS[GREG_HOURS_IN_BREAK][i]; uofaDaysNotCounted += GREG_HOURS_IN_BREAKS[UOFA_DAYS_NOT_COUNTED][i]; } else break; } uofaHoursNotCounted = uofaDaysNotCounted * NUM_HOURS_IN_UOFA_DAY; weeks = (uofaHour + uofaHoursNotCounted) / NUM_HOURS_IN_UOFA_WEEK - irregularUofAWeeks; days = ((uofaHour + uofaHoursNotCounted) % NUM_HOURS_IN_UOFA_WEEK) / NUM_HOURS_IN_UOFA_DAY; gregHoursInIrregWeeks = (NUM_DAYS_IN_UOFA_WEEK * irregularUofAWeeks - uofaDaysNotCounted) * NUM_INVALID_GREG_HOURS_IN_UOFA_DAY + uofaDaysNotCounted * NUM_HOURS_IN_GREG_DAY + gregBreakHours; return uofaHour + GREG_HOUR_ANCHOR + weeks * NUM_INVALID_GREG_HOURS_IN_UOFA_WEEK + days * NUM_INVALID_GREG_HOURS_IN_UOFA_DAY + gregHoursInIrregWeeks; } }