if statements in php using dates - php

I want to write an IF statement based on two dates.
I have a MySQL database (of which I have no control over) for tests and exams taken.
One of the fields is labelled ClientTime and outputs the date and time the test was taken. When queried the typical output would read as such Thu Aug 25 16:47:05 GMT+0100 2011
The following all happens in a while loop
I’ve managed to convert this MySQL date using strtotime() to a d/m/Y format so the above would read 25/08/2011 and I can display a table with all the correct dates.
I also have a php form that asks for the number of days that this test will expire after and this gets stored in a variable $IMonths (from the $_POST['IMonths'] passed from the form page) - the php code will be changed to Months once I have it working but I am using days for the purpose of testing – hence the variable passed being called $IMonths.
I have also created a $today = date("d/m/Y"); variable
I can successfully create a new date using the following command $Expiry = date('d/m/Y', strtotime($row['ClientTime'] . "+$IMonths days")); and can display all results with both the test date and the expiry date.
I then want to include an if-statement within my while-statement that says is ($Expiry>$today) but it’s not accurate – there are no errors and changing the number of days changes the results.
My test database has 5 exams in with the following dates.
Taken 17/08/2011
Taken 17/08/2011
Taken 22/08/2011
Taken 22/08/2011
Taken 24/08/2011
If I set the expiry days to 1, I get all results back as expected:
If I set it to 10 days I get two results
Taken 17/08/2011
Taken 17/08/2011
I don’t get any of the others even though their date will be less than today's date (07/09/2011 (as I write this)) but they do expire in the month of September.
If I set the expiry days to 15, I get one result that is one day in the future!
Taken 17/08/2011
I hope that makes sense. My code is as follows:
<?php
// Make The MySQL Server Connection
mysql_connect("localhost", "root", "") or die(mysql_error());
// Make The MySQL Database Connection
mysql_select_db("questions") or die(mysql_error());
$IQuizName = $_POST['IQuizName'];
$IMonths = $_POST['IMonths'];
$result = mysql_query("SELECT * FROM questions.resultsets
WHERE QuizName='$IQuizName'
AND PassFail='Pass'") or die (mysql_error());
$today = date("d/m/Y");
echo "<table border='1'>";
echo "<tr> <th align='left'>Candidate Name </th> <th align='left'>Pass / Fail</th> <th align='left'>Date last Taken</th> <th align='left'>Expires</th> <th align='left'>Today</th> </tr>";
while($row = mysql_fetch_array($result)){
//START of expiry calculation
$Expiry = date('d/m/Y', strtotime($row['ClientTime'] . "+$IMonths days"));
if($Expiry>$today){
echo "<tr><td>";
echo $row['Candidate'];
echo "</td><td>";
echo $row['PassFail'];
echo "</td><td>";
//Date Conversion
echo date('d/m/Y', strtotime($row['ClientTime']));
echo "</td><td>";
echo $Expiry;
echo "</td><td>";
echo $today;
echo "</td><tr>";
};
}
echo "</table>";
echo "<P>";
?>

Your issue is due to datatypes in PHP. When you call the date() function in PHP, you are actually formatting dates into strings. So when you do $Expiry = date(blahblah), $expiry is now a string. So your if statement is if (somestring > someotherstring). Normally you would not think to compare one block of text to see if it is greater than another block of text.
http://www.php.net/manual/en/function.date.php
One way to get around this would be the strtotime function. This returns integers that are based on UNIX timestamp for the date representation.
http://www.php.net/manual/en/function.strtotime.php
If you convert your string dates to strtotime, your if statement is now comparing if one number is greater than another. This should solve your problem :)

First: fix that SQL-injection hole.
I suggest querying the expiry dates in SQL, it will be much easier.
Here's example code
//escape those user variables !!
$IQuizName = mysql_real_escape_string($_POST['IQuizName']);
$IMonths = mysql_real_escape_string($_POST['IMonths']);
$result = mysql_query("SELECT * FROM questions.resultsets
WHERE QuizName= '$IQuizName'
AND PassFail= 'Pass'
AND ClientTime < NOW() ");
//don't use (or die(error)) in production code, (for now I'll let it slide).
if (!$result) then { die (mysql_error()); }
while ($row = mysql_fetch_row($result))
{
echo "the table"
}

For accurate comparing dates you should convert the dates with the strtotime function again.

In PHP there is no standard date data type. What you have is strings, and when you compare them, they get compared as strings, not as dates, thats why you get results you dont expect. How it normally is done in PHP is to format your date string by ordering from most significant bit to least bit, like
YYYY-MM-DD HH:MM:SS
If you do that, string comparison will work as expected. You can format your dates easily using:
$string = date('Y-m-d H:i:s', $year, $month, $day, $hour, $minute, $second);

Related

How to display number of minutes between two time fields in MySQL?

I'm working on a time management system and am currently stuck. I'm trying to use PHP to calculate the number of hours/minutes between two columns (from and to). These are both set as 'time' type so MySQL recognises it as a time datatype.
I've tried the following in PHP:
$from= isset($_GET['from']) ? '%'.$_GET['from'].'%' : '';
$to = isset($_GET['to']) ? '%'.$_GET['to'].'%' : '';
$diff = $to - $from;
echo "<table border='1'>
echo "<tr>";
echo "<td>" . $row[$diff] . "</td>";
echo "</tr>";
echo "</table>";
Say for example 'to' is set at 15:00:00 and from is set at 09:00:00, then the time difference for that row should be 6 hours and this should be displayed for that row.
The variable $difference is supposed to echo the difference in hours/minutes but it just displays the id assigned to that row instead. I'm trying to echo the number of minutes for each row in the table not just one.
I've seen the timediff function but don't know if that will do the trick.
I don't see your logic with the % and the $_GET vars, and $row suddenly appears out of nowhere.
You should convert the inputted times to php DateTime classes.
An example shows calculating diffs: http://nl1.php.net/manual/en/class.datetime.php#108970
Create your DateTime for example like this:
$dateFrom = new DateTime("2014-02-24 ".$_GET['from']);
$dateTo = new DateTime("2014-02-24 ".$_GET['to']);
$diff = $dateFrom->diff($dateTo);
print_r($diff) ;
The day you use is not really important if you only need the difference in time.

Time Comparisons PHP Nightmare

I'm having an issue with time comparisons with PHP - I think I must be doing something stupid but I've been trying different things for hours now and I'm just hitting a brick wall.
I'm pulling data from EVE's API and then doing a check for whither there is still subscription there and whither there is a skill in training - with both of these there is a particular time frame (1 week for subscription and 12 hours for skills) that I'd like to flag up a warning - however I can't seem to get it working at all. The output of all the dates and times seems to be the right format I just can't get the comparison to work.
I'm wondering if anyone can point what's most likely my stupid mistake and give me a push in the right direction.
thanks for taking a look,
<?php
// ---- For Skill Queue
$apiSection = "char/SkillQueue";
$urlChar = "https://api.eveonline.com/$apiSection.xml.aspx?keyID=$keyID&vCode=$vCode&characterID=$charID";
$data = file_get_contents($urlChar);
$xml = new SimpleXMLElement($data);
foreach ($xml->result->rowset->row as $row){
$charQueueEndTemp = $row{'endTime'};
}
$charQueueEnd = date("d-m-Y H:m", strtotime($charQueueEndTemp));
//echo "Skill Test" . $charQueueEnd;
// --- Account API
$apiSection = "account/AccountStatus";
$urlAccount = "https://api.eveonline.com/$apiSection.xml.aspx?keyID=$keyID&vCode=$vCode";
$data = file_get_contents($urlAccount);
$xml = new SimpleXMLElement($data);
$accSubsTemp = $xml->result->{'paidUntil'}->{0};
$accSubs = date("d-m-Y H:m", strtotime($accSubsTemp));
date_default_timezone_set('Europe/Paris');
$currentDate = date("d-m-Y H:m");
$lessWeek = date("d-m-Y H:m", strtotime("-1 week"));
$plusWeek = date("d-m-Y H:m", strtotime("+1 week"));
$plus12Hour = date("d-m-Y H:m", strtotime("+12 hour"));
//Date Tests
//echo "</br> Curent Date: ".$currentDate;
//echo "</br> Plus Week: ".$plusWeek;
//echo "</br>Acc Subs: ".$accSubs;
//echo "</br>Acc +12: ".$plus12Hour;
// -- Account Subscribed Check
if($currentDate > $accSubs){
echo "Account is not Subscribed";
}
elseif($plusWeek > $accSubs){
echo "Account has less than 1 week Subscription";
}
else{
echo "Account is Subscribed";
}
// -- Skill Training Check
if($charQueueEnd = null){
echo "Skill Queue Ended";
}
elseif($plus12Hour > $charQueueEnd){
echo "Skill Queue ending in less than 12 Hours";
}
else{
echo "Skill Queue Active";
}
?>
Start using DateTime class for date/time manipulation/compare :
If you change your code to this :
$currentDate = new DateTime();
$lessWeek = new DateTime("-1 week");
$plusWeek = new DateTime("+1 week");
$plus12Hour = new DateTime("+12 hour");
... then your IF statements will start to work.
You are doing the date comparisons completely WRONG. You're comparing date STRINGS, e.g. using some dates formatted the same way you're doing:
$plusWeek = '26-08-2013 8:30'; Aug 26th, 2013
$accSubs = '9-08-2013 10:45'; Aug 9th, 2013
Since these are strings, string comparison rules apply. That means the strings are compared character by character, and (string)26 is actually LESS than string(9), because 2 is smaller than 9.
You need to keep things as the raw timestamps, e.g. the strtotime() output:
$plusWeek = strtotime('2013-08-26 08:30'); // 1377527400
$accSubs = strtotime('2013-08-09 10:45').; // 1376066700
Comparing these integer values will work as you want.
The main problem is also that you're not formatted your data strings in "most significant data" order. If they were formatted with the year first, e.g.
yyyy-mm-dd hh:mm:ss
then a string comparison WOULD work as a side effect.
If you want to compare dates you have to compare arguments returned by strtotime() function, for example:
elseif(strtotime($plus12Hour) > strtotime($charQueueEnd)){

Date comparison working as long as time is 00:00:00

this is my events script that pulls out appointments for the next 7 days, it appears to work ok, but only under one condition........The dates and times are held in the mysql db in datetime format so 2013-12-23 08:30:00 . My script prints out each day and finds appointments for that day for customers that are dropping off or picking up things. The mysql looks through the db and matches the customers with the dropping off or picking up fields to the date being printed and adds them in the div below the date.
The problem I am having is that if the time is set to anything other than 00:00:00 it doesn't pickup that customer for that day. How do I get the comparison to ignore the time and only use the date ?.
// Date box container
echo '<div class="dateboxcontainer">';
// Loop through and create a date for the next 7 days
$days = new DatePeriod(new DateTime, new DateInterval('P1D'), 7);
foreach ($days as $day) {
echo '<div class="datebox">';
echo '<div class="topdate">';
echo strtoupper($day->format('D d')) . PHP_EOL;
echo '</div>';
// Get the names for each day
$theday = strtoupper($day->format('Y-m-d'));
$sqldate = <<<SQL
SELECT *
FROM `jobdetails`
WHERE datedroppingoff = '$theday' OR datepickingup = '$theday'
SQL;
if(!$resultdate = $db->query($sqldate)){
die('There was an error running the query [' . $db->error . ']');
}
while($rowdate = $resultdate->fetch_assoc()){
echo $rowdate['name'];
}
//
echo '</div>';
}
echo '</div>';
//
What you are doing right now is comparing date/time values to just date values. This comparison would fail if the time part is anything other than midnight.
You can fix the comparison by using the DATE() MySql function to compare apples with apples:
WHERE DATE(datedroppingoff) = '$theday' OR DATE(datepickingup) = '$theday'
There are other ways to do the same, for example
WHERE DATEDIFF(datedroppingoff, '$theday') = 0 OR ...
If you had a $nextday value at hand you could also do
WHERE (datedroppingoff >= '$theday' AND datedroppingoff < '$nextday') OR ...
You are storing a specific time and day in mySQL, but only search for a date in your SQL query. As mySQL does not understand the difference between you wanting to search for a complete day or a specific point in time, mySQL assumes you are looking for the day at time 0:00:00.
You have a few options, you could search for a time period (pseudo code, check the borders yourself):
WHERE datedroppingoff > '$theday' AND datedroppingoff < '$theday'+1
another option is to store the date and time in separate db fields. That way you can keep your SQL queries simpler.
Good luck.

Optional month or day in MySQL date field from PHP

I have a problem where I need to handle dates where the month and day parts are optional. For example, the year will always be known but sometimes the day or month and day will be unknown.
In MySQL I can create a table with a date field and while I can't find any reference in the MySQL Manual it will accept the following as valid:
(YYYY-MM-DD format):
2011-02-10 // Current date
2011-02-00 // Day unknown so replaced with 00
2011-00-00 // Day and month unkown so replaced with 00-00
Test calculations from within the database work fine so I can still sort results easily. In the manual it says that month needs to be between 01 and 12, and day between 01 and 31 - but it does accept 00.
First question: Am I going to run into trouble using 00 in the month or day parts or is this perfectly acceptable?
Next question: Is there a PHP function (or MySQL format command) that will automatically format the following dates into the required format string?
2011 becomes 2011-00-00
2011-02 becomes 2011-02-00
Or do I need write a special function to handle this?
The following doesn't work:
<?php
$date = date_create_from_format('Y-m-d', '2011-00-00');
echo date_format($date, 'Y-m-d');
// Returns 2010-11-30
$date = date_create_from_format('Y-m-d', '2011-02-00');
echo date_format($date, 'Y-m-d');
// Returns 2011-01-31
?>
Third question: Is there a PHP function (or MySQL command) to format the dates for use in PHP?
Finally, is this the best approach? Or is there a 'best practise' method?
EDIT:
Here is what I'm currently doing:
A date field can accept a date in the format YYYY, YYYY-MM, or YYYY-MM-DD and before sending to the database it is processed in this function:
/**
* Takes a date string in the form:
* YYYY or
* YYYY-MM or
* YYYY-MM-DD
* and validates it
*
* Use date_format($date, $format); to reverse.
*
* #param string $phpDate Date format [YYYY | YYYY-MM | YYYY-MM-DD]
*
* #return array 'date' as YYYY-MM-DD, 'format' as ['Y' | 'Y-m' | 'Y-m-d'] or returns false if invalid
*/
function date_php2mysql($phpDate) {
$dateArr = false;
// Pattern match
if (preg_match('%^(?P<year>\d{4})[- _/.]?(?P<month>\d{0,2})[- _/.]?(?P<day>\d{0,2})%im', trim($phpDate), $parts)) {
if (empty($parts['month'])) {
// Only year valid
$date = $parts['year']."-01-01";
$format = "Y";
} elseif (empty($parts['day'])) {
// Year and month valid
$date = $parts['year']."-".$parts['month']."-01";
$format = "Y-m";
} else {
// Year month and day valid
$date = $parts['year']."-".$parts['month']."-".$parts['day'];
$format = "Y-m-d";
}
// Double check that it is a valid date
if (strtotime($date)) {
// Valid date and format
$dateArr = array('date' => $date, 'format' => $format);
}
} else {
// Didn't match
// Maybe it is still a valid date
if (($timestamp = strtotime($phpDate)) !== false) {
$dateArr = array('date' => date('Y-m-d', $timestamp), 'format' => "Y-m-d");
}
}
// Return result
return $dateArr;
}
So it pattern matches the input $phpDate where it must begin with 4 digits, then optionally pairs of digits for the month and the day. These are stored in an array called $parts.
It then checks if months or days exist, specifying the format string and creating the date.
Finally, if everything checks out, it returns a valid date as well as a format string. Otherwise it returns FALSE.
I end up with a valid date format for my database and I have a way of using it again when it comes back out.
Anyone think of a better way to do this?
I have a problem where I need to handle dates where the month and day parts are optional.
For example, the year will always be known but sometimes the day or month and day will be
unknown.
In many occasions, we do need such 'more or less precise' dates, and I use such dates as 2011-04-01 (precise), as well as 2011-04 (= April 2011) and 2011 (year-only date) in archives metadata. As you mention it, MySQL date field tolerates '2011-00-00' though no FAQs tell about it, and it's fine.
But then, I had to interface the MySQL database via ODBC and the date fields
are correctly translated, except the 'tolerated' dates (Ex: '2011-04-00' results empty in the resulting MySQL-ODBC-connected ACCESS database.
For that reason, I came to the conclusion that the MySQL date field could be converted in a plain VARCHAR(10) field : As long as we don't need specific MySQL date functions, it works fine, and of course, we can still use php date functions and your fine date_php2mysql() function.
I would say that the only case when a MySQL date field is needed
is when one needs complex SQL queries, using MySQL date functions in the query itself.
(But such queries would not work anymore on 'more or less precise' dates!...)
Conclusion : For 'more or less precise' dates,
I presently discard MySQL date field and use plain VARCHAR(10) field
with aaaa-mm-jj formated data. Simple is beautiful.
Since the data parts are all optional, would it be tedious to store the month, day, and year portions in separate integer fields? Or in a VARCHAR field? 2011-02-00 is not a valid date, and I wouldnt't think mysql or PHP would be excited about it. Test it out with str_to_time and see what kind of results you get, also, did you verify that the sorting worked right in MySQL? If the docs say that 1 through 31 is required, and it is taking 00, you might be relying on what is, in essence, a bug.
Since 2011-02-00 is not a valid date, none of PHP's formatting functions will give you this result. If it handled it at all, I wouldn't be surprised if you got 2001-01-31 if you tried. All the more reason to either store it as a string in the database, or put the month, day, and year in separate integer fields. If you went with the latter route, you could still do sorting on those columns.
I have also encountered this problem. I ended up using the PEAR Date package. Most date classes won't work with optional months or optional days, but the PEAR Date package does. This also means you don't need custom formatting functions and can use the fancy formatting methods provided by the Date package.
I have found this link in a textbook. This states that month and day values can be zero to allow for the possiblity of storing incomplete or unknown data
http://books.google.co.uk/books?id=s_87mv-Eo4AC&pg=PA145&lpg=PA145&dq=mysql+date+of+death+when+month+unknown&source=bl&ots=tcRGz3UDtg&sig=YkwpkAlDtBP1KKTDtqSyZCl63hs&hl=en&ei=Btf5TbL1NIexhAfkveyTAw&sa=X&oi=book_result&ct=result&resnum=8&ved=0CFMQ6AEwBw#v=onepage&q&f=false
If you pull your date in pieces from the database you can get it as if it's 3 fields.
YEAR(dateField) as Year, MONTH(dateField) as Month, DAY(dateField) as DAY
Then pushing those into the corresponding fields in the next bit of PHP will give you the result you're looking for.
$day = 0;
$month = 0;
$year = 2013;
echo $datestring;
$format = "Y";
if($month)
{
$format .= "-m";
if($day)
$format .="-d";
else
$day = 1;
}
else
{
$month = 1;
$day = 1;
}
$datestring = strval($year)."-".strval($month)."-".strval($day);
$date = date($format, strtotime($datestring));
echo $date; // "2013", if $month = 1, "2013-01", if $day and $month = 1, "2013-01-01"

Looping through dates until a free one is found

I have a function which checks my database to see if a date exists, if it does exist, i want to display the next date which isnt in the database.
Is this possible?
My function returns 1 if there is a date in the database and 0 if there isnt, im using codeigniter, but not using any built in functions.
Its basically an availability checker, it allows us to input many different dates in the database, so calling my function i use
$availcheck = $ci->availability->check_availability_by_date(date('d/m/Y'));
The i use a if statement to check if the first time it runs it returns a value, this is how i have it
if($availcheck > 0){
// loop through the next dates and run the function again to see if it returns 0
} else {
echo 'available now';
}
I guess i would add 1 to the current date, check that one, then add another 1 and check that and so on.
Im just not sure how.
Cheers,
if i understand you correct , your problem is adding the day ?
if so i would suggest using the epoch or unix time
so convert the date to unix time using mktime than just add 1 day in seconds (24*60*60)
and then convert back to d/m/y format.
you can use the date function.
$date = time(); // get current timestamp
while ($availcheck) // while date IS found in database
{
$availcheck = $ci->availability->check_availability_by_date(date('d/m/Y',$date));
$date = $date + (24*60*60); // add one day
}
$date = $date - (24*60*60); // reduce one day
echo date('d/m/Y',$date); // prints the first date that is not in the DB
This SQL code could work for me.
$today = date("Y-m-d"); //today
$sql = "SELECT date FROM calendar WHERE date>'{$today}' AND date<='2100-12-31' AND date='0000-00-00' LIMIT 1";
Since you can't determine the ending date, 2100 could be for testing.

Categories