Hi guys. I'm currently writing an application that includes functions to add employees to a work roster. I've written a validation routine that checks to see if the employee is already working during the hours that the user inputs, if they are, it's to return a true status, if not then it's to return false. Now, my main problem is, the format i have to work with is this:
Commence Date - Date the period starts
Finish Date - Date the period finishes
Commence Time - Starting Time each day of the period
Finish Time - Finish time each day period
That's all I have, but I have to validate for each date and time between the commence and finish times. Now, what I've got WORKS, but it just seems way too big to me, and I would appreciate it if someone would have a looksey and tell me if they can think of a better way to do it:
<?php
class validate_times {
/*
Date Created: 5/12/03 8:30AM
Last Updated: 5/12/03 2:03PM
Updated By: Matt Magin
Description: This class is used to validate the times assigned to an employee from
the work roster. It checks to see if an employee is already set to work
during the range of times allocated, if they are then set the bMatch
boolean to true, otherwise keep it as false.
*/
// Define the variables to be used in the class
var $db; // Object - Database connection object
var $sDbName; // String - Name of database to use
var $aInput; // Array - Input from user
var $aNewInput; // Array - Modified user input
var $aCurrDates;// Array - Current dates that conflict with the range input
var $bMatch; // Boolean - Return of compare function, checks if it was matched
var $sError; // String - Error message (if there was one)
function validate_times($db, $sDbName, $aInput) {
/* This is the constructor. It sets everything, checks if there was an error
getting the data from the database, if not, runs the datetime comparison,
if there was, set an error */
$this->db = $db; // Set the database object
$this->sDbName = $sDbName; // Set the database name
$this->aInput = $aInput; // Set the User input
$this->set_new_input();
$this->set_curr_dates();
$this->compare();
}
function set_new_input() {
// Create a Unix Timestamp for the dates
$this->aNewInput['iStartDate'] = strtotime(date_to_mysql($this->aInput['date_commence']));
$this->aNewInput['iEndDate'] = strtotime(date_to_mysql($this->aInput['date_finish']));
// Format the times into seconds from 00:00
$aTimeArray = explode(":", $this->aInput['time_commence']);
$this->aNewInput['iStartTimeSec'] = ($aTimeArray[0]*60 + $aTimeArray[1])*60;
$aTimeArray = explode(":", $this->aInput['time_finish']);
$this->aNewInput['iFinishTimeSec'] = ($aTimeArray[0]*60 + $aTimeArray[1])*60;
if($this->aNewInput['iStartTimeSec'] > $this->aNewInput['iFinishTimeSec']) {
/* If the Start time is greater than the finish time, it's spanning
multiple dates. As such, add 24 hours worth of seconds to the timestamp
so it's looking at the correct time. */
$this->aNewInput['iFinishTimeSec'] = $this->aNewInput['iFinishTimeSec'] + 86400;
}
}
function set_curr_dates() {
/* This function gets all the records from the database that conflict with
the dates supplied in iStartDate and iEndDate */
// Create the query
$sql = "SELECT UNIX_TIMESTAMP(date_commence) as date_commence, ";
$sql .= "UNIX_TIMESTAMP(date_finish) as date_finish, ";
$sql .= "TIME_TO_SEC(time_commence) as time_commence, ";
$sql .= "TIME_TO_SEC(time_finish) as time_finish ";
$sql .= "FROM ".$this->sDbName.".work_roster ";
$sql .= "WHERE employee_id='".$this->aInput['employee_id']."' ";
$sql .= "AND ('".$this->aNewInput['iStartDate']."' <= UNIX_TIMESTAMP(date_commence) ";
$sql .= "AND '".$this->aNewInput['iEndDate']."' >= UNIX_TIMESTAMP(date_commence)) ";
$sql .= "OR ('".$this->aNewInput['iStartDate']."' <= UNIX_TIMESTAMP(date_finish) ";
$sql .= "AND '".$this->aNewInput['iEndDate']."' >= UNIX_TIMESTAMP(date_finish)) ";
$sql .= "OR ('".$this->aNewInput['iStartDate']."' >= UNIX_TIMESTAMP(date_commence) ";
$sql .= "AND '".$this->aNewInput['iEndDate']."' <= UNIX_TIMESTAMP(date_finish))";
// Run the query
$Result = $this->db->Execute($sql);
// Otherwise add the data returned to a multidimensional array (aCurrDates)
$i = 0; // Set the row counter to 0
$this->aCurrDates = array(); // Make sure aCurrDates is defined as an array
while($aRow = $Result->FetchRow()) {
$this->aCurrDates[$i] = $aRow; // Add the row to the array
if($this->aCurrDates[$i]['time_commence'] > $this->aCurrDates[$i]['time_finish']) {
/* Check that the Commence time is less than the finish time. If it's NOT, then
the finish time should be 24 hrs ahead of what it currently, so add 86400
seconds to it to ensure it's the correct date */
$this->aCurrDates[$i]['time_finish'] = $this->aCurrDates[$i]['time_finish'] + 86400;
}
$i++; // Increment the row counter
}
}
function compare() {
$this->bMatch = false; // Assume there is no match
if(empty($this->aCurrDates)) {
return;
}
foreach($this->aCurrDates as $aCurrent) {
/* Loop through each row returned from the database.
Set the Commence times and Finish times, and use the End Timestamp as a condition
for the while loops. The Commence and Finish times will be incremented by
24 hours each iteration, so that each day in the range is tested */
$NewCommenceTS = $this->aNewInput['iStartDate'] + $this->aNewInput['iStartTimeSec'];
$NewFinishTS = $this->aNewInput['iStartDate'] + $this->aNewInput['iFinishTimeSec'];
$NewEndTS = $this->aNewInput['iEndDate'] + $this->aNewInput['iFinishTimeSec'];
while($NewFinishTS <= $NewEndTS) {
/* Loop through each day in the New Range of dates.
Set the Commence and Finish times for the Current Range pulled from
the database, for the same reasons stated above */
$CurrCommenceTS = $aCurrent['date_commence'] + $aCurrent['time_commence'];
$CurrFinishTS = $aCurrent['date_commence'] + $aCurrent['time_finish'];
$CurrEndTS = $aCurrent['date_finish'] + $aCurrent['time_finish'];
while($CurrCommenceTS <= $CurrEndTS) {
/* Check if Any of the timestamps overlap, if they do then set the
match variable to true, if not, continue checking until the looping
is finished */
if(($CurrCommenceTS <= $NewCommenceTS && $CurrFinishTS >= $NewCommenceTS) ||
($CurrCommenceTS <= $NewFinishTS && $CurrFinishTS >= $NewFinishTS) ||
($CurrCommenceTS >= $NewCommenceTS && $CurrFinishTS <= $NewFinishTS)) {
$this->bMatch = true;
return; // Break out of the function to prevent extra processing
}
// Increment the times by 24 hrs
$CurrCommenceTS = $CurrCommenceTS + 86400;
$CurrFinishTS = $CurrFinishTS + 86400;
}
// Increment the times by 24 hrs
$NewCommenceTS = $NewCommenceTS + 86400;
$NewFinishTS = $NewFinishTS + 86400;
}
}
}
}
?>