= CONFIGHARD_DATEFUNC_MINYEAR) && ($year_in < CONFIGHARD_DATEFUNC_MAXYEAR)) { //In year $year_in, the number of prior years where the year was divisible //by 4 is given by the expression below. if ($year_in == CONFIGHARD_DATEFUNC_MINYEAR) { $years_prior_div_4 = 0; } else { $years_prior_div_4 = (int)(($year_in - 1 - CONFIGHARD_DATEFUNC_MINYEAR) / 4); //Verified in the PHP docs that cast to int from float behaves with classic //div behavior (rounding down), so will be OK. } //Correct for the fact that 1800, 1900, 2100, and 2200 are not leap years, but 2000 is. if (($year_in > 1800) && ($year_in <= 1900)) { //1800 was not a leap year, so we need to deduct 1 from the total leap years encountered. $years_prior_div_4 -= 1; } else if (($year_in > 1900) && ($year_in <= 2100)) { //1800 was not a leap year, and 1900 was not a leap year (but 2000 was), //so we need to deduct 2 from the total leap years encountered. $years_prior_div_4 -= 2; } else if (($year_in > 2100) && ($year_in <= 2200)) { //1800, 1900, and 2100 were not leap years (but 2000 was), //so we need to deduct 3 from the total leap years encountered. $years_prior_div_4 -= 3; } else /* if (($year_in > 2200) && ($year_in <= 2300)) */ { //1800, 1900, 2100, and 2200 were not leap years (but 2000 was), //so we need to deduct 4 from the total leap years encountered. $years_prior_div_4 -= 4; } //The total number of days in years prior is going to be 365 times the number //of years prior, except we need to add a day for each leap year prior. if ($year_in == CONFIGHARD_DATEFUNC_MINYEAR) { return(0); } else { return((int)(($year_in - CONFIGHARD_DATEFUNC_MINYEAR) * 365 + $years_prior_div_4)); } } else { //Not a year we can calculate about. Don't want to error-trap at such a //low level. Just return zero. return(0); } } // // //-------------------------------------------------------------------------------- //Calculates the number of days in a given month of a given year. Years are //2000 ... (i.e. full-sized integer), and months are referenced in the traditional //way, 1..12. // //Unit-tested 20060408. // function DATEFUNC_year_month_days($year, $month) { switch ($month) { default: case 1: return(31); break; case 2: if (DATEFUNC_year_days($year) == 365) { return(28); } else { return(29); } break; case 3: return(31); break; case 4: return(30); break; case 5: return(31); break; case 6: return(30); break; case 7: return(31); break; case 8: return(31); break; case 9: return(30); break; case 10: return(31); break; case 11: return(30); break; case 12: return(31); break; } } // // //-------------------------------------------------------------------------------- //Calcualtes the Julian offset of a date within a certain year. The offset //of January 1 of any year is 0. Year, month, and day are 2000 ..., 1 ..., and //1 ..., respectively. // //Unit-tested 20060408. // function DATEFUNC_year_julian_offset($year, $month, $day) { switch ($month) { default: case 1: return($day - 1); break; case 2: return(31 + $day - 1); case 3: if (DATEFUNC_year_days($year) == 365) { return(59 + $day - 1); } else { return(59 + $day); } break; case 4: if (DATEFUNC_year_days($year) == 365) { return(90 + $day - 1); } else { return(90 + $day); } break; case 5: if (DATEFUNC_year_days($year) == 365) { return(120 + $day - 1); } else { return(120 + $day); } break; case 6: if (DATEFUNC_year_days($year) == 365) { return(151 + $day - 1); } else { return(151 + $day); } break; case 7: if (DATEFUNC_year_days($year) == 365) { return(181 + $day - 1); } else { return(181 + $day); } break; case 8: if (DATEFUNC_year_days($year) == 365) { return(212 + $day - 1); } else { return(212 + $day); } break; case 9: if (DATEFUNC_year_days($year) == 365) { return(243 + $day - 1); } else { return(243 + $day); } break; case 10: if (DATEFUNC_year_days($year) == 365) { return(273 + $day - 1); } else { return(273 + $day); } break; case 11: if (DATEFUNC_year_days($year) == 365) { return(304 + $day - 1); } else { return(304 + $day); } break; case 12: if (DATEFUNC_year_days($year) == 365) { return(334 + $day - 1); } else { return(334 + $day); } break; } } // // //-------------------------------------------------------------------------------- //Given year, month, and day (2000 ..., 1 ..., 1 ...), returns an integer //representing the day of the week. // 0 : Sunday // 1 : Monday // 2 : Tuesday // 3 : Wednesday // 4 : Thursday // 5 : Friday // 6 : Saturday // //Unit-tested 20060408. // function DATEFUNC_intdayofweek_intdate($year, $month, $day) { $int_differential = CONFIGHARD_DATEFUNC_EPOCH_DOW + DATEFUNC_year_predecessor_sum($year) + DATEFUNC_year_julian_offset($year, $month, $day); return($int_differential % 7); } //-------------------------------------------------------------------------------- //Compares two dates, expressed as integers. Both must be properly formatted //(i.e. valid years, months, and days). Returns: // -1 if a < b. // 0 if a == b. // 1 if a > b. // function DATEFUNC_cmp($ya, $ma, $da, $yb, $mb, $db) { if ($ya < $yb) { return(-1); } else if ($ya > $yb) { return(1); } else { if ($ma < $mb) { return(-1); } else if ($ma > $mb) { return(1); } else { if ($da < $db) { return(-1); } else if ($da > $db) { return(1); } else { return(0); } } } } // // //-------------------------------------------------------------------------------- //Given a year, a month, and a month offset, moves the passed date backward //(in the case of negative month offset) or forward (in the case of positive //month offset) and calculates a new year and month. The calculated returned //value will not go outside the range set in CONFIGHARD.INC for the //scheduling range. // //A result flag is set to: // -1 : If the result had to be clipped because it went outside the calendar // functionality window. // 0 : If the result did not have to be clipped. // 1 : If the result had to be clipped because it went outside the calendar // functionality window. // //The values passed in must be valid. // //The ordinal month approach is used because integer math tends to be //very fast. // function DATEFUNC_offset_month($year_in, $month_in, $month_offset_in, &$year_out, &$month_out, &$result_out) { //Default value of result. $result_out = 0; //Create ordinal month representations of the min and max allowable months. Using this //scheme, the 0'th month would be January of 0 A.D. $min_ordinal_month = CONFIGHARD_DATEFUNC_MINYEAR * 12; $max_ordinal_month = CONFIGHARD_DATEFUNC_MAXYEAR * 12 - 1; //Create ordinal month representation of the input year, month. $in_ordinal_month = $year_in * 12 + $month_in - 1; //Create the ordinal month reprsentation of the input + offset. $calcd_ordinal_month = $in_ordinal_month + $month_offset_in; //Clip the result to be within the scheduling range of the FBO-prime software. if ($calcd_ordinal_month < $min_ordinal_month) { $calcd_ordinal_month = $min_ordinal_month; $result_out = -1; } else if ($calcd_ordinal_month > $max_ordinal_month) { $calcd_ordinal_month = $max_ordinal_month; $result_out = 1; } //Convert back to calendar year and month format. $year_out = (int) ($calcd_ordinal_month / 12); $month_out = ($calcd_ordinal_month % 12) + 1; } // // //-------------------------------------------------------------------------------- //Calculates the date one week ago. The date passed in must be within the //calendaring range and the date one week before must be also within //calendaring range. // function DATEFUNC_one_week_ago($year_in, $month_in, $day_in, &$year_out, &$month_out, &$day_out) { if (($day_in - 7) > 0) { //Simplest case. Different date within the same month. $year_out = $year_in; $month_out = $month_in; $day_out = $day_in - 7; } else { //Have to roll the month backwards. if ($month_in > 1) { //Have to roll day and month backwards, but not the year. $year_out = $year_in; $month_out = $month_in - 1; $day_out = $day_in - 7 + DATEFUNC_year_month_days($year_in, $month_in - 1); } else { //Have to roll back the day, month, and year. $year_out = $year_in - 1; $month_out = 12; $day_out = $day_in - 7 + DATEFUNC_year_month_days($year_in - 1, 12); } } } // //-------------------------------------------------------------------------------- //Calculates the date one week in the future. The date passed in must be within the //calendaring range and the date one week in the future must be also within //calendaring range. // function DATEFUNC_one_week_future($year_in, $month_in, $day_in, &$year_out, &$month_out, &$day_out) { $days_in_month = DATEFUNC_year_month_days($year_in, $month_in); if (($day_in + 7) <= $days_in_month) { //Simplest case. Different date within the same month. $year_out = $year_in; $month_out = $month_in; $day_out = $day_in + 7; } else { //Have to roll the month forward. if ($month_in < 12) { //Have to roll day and month forward, but not the year. $year_out = $year_in; $month_out = $month_in + 1; $day_out = $day_in + 7 - $days_in_month; } else { //Have to roll forward the day, month, and year. $year_out = $year_in + 1; $month_out = 1; $day_out = $day_in + 7 - $days_in_month; } } } // //-------------------------------------------------------------------------------- //Calculates the date one day ago. The date passed in must be within the //calendaring range and the date one day before must be also within //calendaring range. // function DATEFUNC_one_day_ago($year_in, $month_in, $day_in, &$year_out, &$month_out, &$day_out) { if ($day_in > 1) { //Simplest case. Different date within the same month. $year_out = $year_in; $month_out = $month_in; $day_out = $day_in - 1; } else { //Have to roll the month backwards. if ($month_in > 1) { //Have to roll day and month backwards, but not the year. $year_out = $year_in; $month_out = $month_in - 1; $day_out = DATEFUNC_year_month_days($year_in, $month_in - 1); } else { //Have to roll back the day, month, and year. $year_out = $year_in - 1; $month_out = 12; $day_out = DATEFUNC_year_month_days($year_in - 1, 12); } } } // //-------------------------------------------------------------------------------- //Calculates the date one day in the future. The date passed in must be within the //calendaring range and the date one day in the future must be also within //calendaring range. // function DATEFUNC_one_day_future($year_in, $month_in, $day_in, &$year_out, &$month_out, &$day_out) { $days_in_month = DATEFUNC_year_month_days($year_in, $month_in); if ($day_in < $days_in_month) { //Simplest case. Different date within the same month. $year_out = $year_in; $month_out = $month_in; $day_out = $day_in + 1; } else { //Have to roll the month forwards. if ($month_in < 12) { //Have to roll day and month forward, but not the year. $year_out = $year_in; $month_out = $month_in + 1; $day_out = 1; } else { //Have to roll forward the day, month, and year. $year_out = $year_in + 1; $month_out = 1; $day_out = 1; } } } // //-------------------------------------------------------------------------------- //Given a year and a month, indicates whether it is within the window of //what should be viewable for scheduling. // //The criteria for displaying the month are: // a)The month is not outside the calendaring functionality window. // b)The month is not outside the parameters set by the // configuration constants CONFIG_SCHED_SCHEDACC_PREV_MO or // CONFIG_SCHED_SCHEDACC_FUTU_MO, which specify how many months // previous and future may be viewed. // //Returns: // -1 : If the year/month is too early to be // schedulable. // 0 : If the year/month should be schedulable. // 1 : If the year/month is too late to be schedulable. // function DATEFUNC_is_not_displayable($year_in, $month_in) { global $GLOBAL_stime_year; global $GLOBAL_stime_month; //If the year is out of bounds, it is a no-go. if ($year_in < CONFIGHARD_DATEFUNC_MINYEAR) return(-1); else if ($year_in >= CONFIGHARD_DATEFUNC_MAXYEAR) return(1); //If the month is out of bounds, it is a no-go. if (($month_in < 1) || ($month_in > 12)) return(1); //Arbitrary, as long as it isn't 0. //For reference, find the year/month that is CONFIG_SCHED_SCHEDACC_PREV_MO //behind the passed year/month. If this is clipped, no harm done. DATEFUNC_offset_month($GLOBAL_stime_year, $GLOBAL_stime_month, -CONFIG_SCHED_SCHEDACC_PREV_MO, $year_lower_limit, $month_lower_limit, $result_flag); //For reference, find the year/month that is CONFIG_SCHED_SCHEDACC_FUTU_MO //ahead of the passed year/month. If this is clipped, no harm done. DATEFUNC_offset_month($GLOBAL_stime_year, $GLOBAL_stime_month, CONFIG_SCHED_SCHEDACC_FUTU_MO, $year_upper_limit, $month_upper_limit, $result_flag); //echo " year upper limit : " . $year_upper_limit . " month_upper_limit : " . $month_upper_limit . " "; //If the passed year/month are below the lower limit, this means it isn't //displayable. if (DATEFUNC_cmp($year_in, $month_in, 1, $year_lower_limit, $month_lower_limit, 1) == -1) return(-1); //If the passed year/month are above the upper limit, this means it isn't //displayable. if (DATEFUNC_cmp($year_in, $month_in, 1, $year_upper_limit, $month_upper_limit, 1) == 1) return(1); //If we're here, it is displayable. return(0); } // //================================================================================ //================================================================================ //==== S T R I N G M A P P I N G ============================================ //================================================================================ //================================================================================ // //Returns the string associated with an ordinal month number 1-12. // function DATEFUNC_string_month_long($month_no) { $lookup = array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); if (($month_no < 1) || ($month_no > 12)) { return("INVALID"); } else { return($lookup[$month_no - 1]); } } // //-------------------------------------------------------------------------------- //Returns the string associated with a day of the week 0-6. // function DATEFUNC_string_dow_long($dow_no) { $lookup = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"); if (($dow_no < 0) || ($dow_no > 6)) { return("INVALID"); } else { return($lookup[$dow_no]); } } //-------------------------------------------------------------------------------- //Returns a string representing the standard date, i.e. "January 19, 2009" or //whatever. // function DATEFUNC_stdlongdate($year, $month, $day) { return(DATEFUNC_string_month_long($month) . " " . $day . ", " . $year); } // //-------------------------------------------------------------------------------- //Returns a string representing the standard date with day of the week, //i.e. "Friday, January 19, 2009" or whatever. // function DATEFUNC_stdlongdate_w_dow($year, $month, $day) { $dow = DATEFUNC_intdayofweek_intdate($year, $month, $day); return( DATEFUNC_string_dow_long($dow) . ", " . DATEFUNC_string_month_long($month) . " " . $day . ", " . $year); } // //-------------------------------------------------------------------------------- //Returns a string representing the standard time. In non-military format, //this will be something like 5:04 p.m. In military time, something like //17:04. // function DATEFUNC_stdtimenosec($hour, $minute) { if (CONFIG_TIME_FORMAT_24HR) { //24-hour format. return(sprintf("%02d", $hour) . ":" . sprintf("%02d", $minute)); } else { //12-hour format. if ($hour == 0) { return(sprintf("%d", 12) . ":" . sprintf("%02d", $minute) . " a.m."); } else if ($hour < 12) { return(sprintf("%d", $hour) . ":" . sprintf("%02d", $minute) . " a.m."); } else if ($hour == 12) { return(sprintf("%d", $hour) . ":" . sprintf("%02d", $minute) . " p.m."); } else { return(sprintf("%d", $hour - 12) . ":" . sprintf("%02d", $minute) . " p.m."); } } } // //-------------------------------------------------------------------------------- //Calculate and return an array of Boolean results to determine whether it is OK //to view/schedule the indicated date/time. Each Boolean result is TRUE if it is //OK to view/schedule or FALSE if not. // // a)[0] A month ago. // b)[1] A week ago. // c)[2] A day ago. // d)[3] One panel back. // e)[4] One panel forward. // f)[5] One day forward. // g)[6] One week forward. // h)[7] One month forward. // function DATEFUNC_viewschedtime_differential_array($dispyear, $dispmonth, $dispday, $disphour, $dispminute) { global $CONFIG_SCHED_DAY_PANELS; //Default to all FALSE so we don't forget anything. // $rv = array(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); //NOW //--- //For reference, determine if the base display date passed in is //displayable/schedulable. // if (DATEFUNC_is_not_displayable($dispyear, $dispmonth) == 0) $base_date_is_ok = TRUE; else $base_date_is_ok = FALSE; //A MONTH AGO //----------- //First, try to back off one month to get to the previous month. If we fail on this //(because we're at the lower limit of what the calendar functionality can handle), //then we definitely can't display the previous month. // DATEFUNC_offset_month($dispyear, $dispmonth, -1, $prev_month_year, $prev_month_month, $prev_month_result_code); if ($prev_month_result_code == 0) { //We are not up against the limit of the calendaring functionality. //Evaluate the previous month. // if (DATEFUNC_is_not_displayable($prev_month_year, $prev_month_month) == 0) { $rv[0] = TRUE; //Seems OK. } else { $rv[0] = FALSE; //Is outside the viewable range. } } else { //We couldn't back off because we were at the limit. $rv[0] = FALSE; } //A WEEK AGO //----------- //The logic for a week ago is that if the day of the month is seven or less, the previous //month is relevant, else the current month is relevant. if ($dispday <= 7) $rv[1] = $rv[0]; else $rv[1] = $base_date_is_ok; //A DAY AGO //----------- //The logic for a day ago is that if the day of the month is 1, the previous //month is relevant, else the current month is relevant. if ($dispday == 1) $rv[2] = $rv[0]; else $rv[2] = $base_date_is_ok; //ONE PANEL BACK //-------------- //Get the currently appropriate panel. $panel = TOD_best_panel($disphour, $dispminute, $CONFIG_SCHED_DAY_PANELS); // //If the current panel is not 0, backing off the panel won't change the date, //and so the passed date's status is the right thing to look at. // //If the current panel is 0, backing off will move the date to the previous //day, and we use that status. if ($panel != 0) { $rv[3] = $base_date_is_ok; } else { $rv[3] = $rv[2]; } //A MONTH IN THE FUTURE //--------------------- //First, try to go forward one month to get to the next month. If we fail on this //(because we're at the upper limit of what the calendar functionality can handle), //then we definitely can't display the next month. // DATEFUNC_offset_month($dispyear, $dispmonth, 1, $next_month_year, $next_month_month, $next_month_result_code); if ($next_month_result_code == 0) { //We are not up against the limit of the calendaring functionality. //Evaluate the next month. // if (DATEFUNC_is_not_displayable($next_month_year, $next_month_month) == 0) { $rv[7] = TRUE; //Seems OK. } else { $rv[7] = FALSE; //Is outside the viewable range. } } else { //We couldn't go forward because we were at the limit. $rv[7] = FALSE; } //A WEEK IN THE FUTURE //-------------------- //The logic for a week in the future is that if going forward 7 days will put us //into the next month, then the validity of that applies, otherwise the //validity for the current month applies. $days_in_base_month = DATEFUNC_year_month_days($dispyear, $dispmonth); if (($dispday + 7) > $days_in_base_month) { //Get value from next month. $rv[6] = $rv[7]; } else { //Get value from this month. $rv[6] = $base_date_is_ok; } //A DAY IN THE FUTURE //------------------- //The logic for a day in the future is that if the current day is the last day of //the month, then next month's value applies, otherwise this month's //value applies. if ($dispday >= $days_in_base_month) $rv[5] = $rv[7]; //Next month's value. else $rv[5] = $base_date_is_ok; //This month's value. //ONE PANEL IN THE FUTURE //----------------------- //If the current panel is not the last one, going to the next panel won't change //the date, and so the passed date's status is the right thing to look at. // //If the current panel is the last one, going forward will move the date to the //next day, and we use that status. $npanels = (int)(count($CONFIG_SCHED_DAY_PANELS) / 2); if ($panel >= ($npanels - 1)) //Last penel test. { $rv[4] = $rv[5]; } else { $rv[4] = $base_date_is_ok; } //Return the return value. return($rv); } // //-------------------------------------------------------------------------------- //End of $RCSfile: datefunc.inc,v $. //-------------------------------------------------------------------------------- ?>