comparing timestamps - php

HI, My php is very rusty and I can't quite remember how to do this.
I have a script that i only want to call every 15 minutes. I've created a table called last_updated. What I want to do is have some code at the top of my script that queries this last_updated table and if now() minus the last updated is greater than 15 minutes then run the script and also update last_updated to now...if it isn't don't run the script. Does this make sense?
Now I know when I'm updating last_updated I need to use now() To put a new timestamp in but I;m not sure how to do the comparing of now with the db value to see if it's greater then 15 mins.
Any ideas

<?php
$pdo = new PDO('mysql:host=your_host;dbname=your_database', $user, $password, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
// query the database. change
$stmt = $pdo->query('SELECT UNIX_TIMESTAMP(last_updated_date) FROM last_updated ORDER BY last_updated_date DESC LIMIT 1');
$lastUpdatedTimestamp = $stmt->fetch(PDO::FETCH_COLUMN);
if ((time() - $lastUpdatedTimestamp) > (60 * 15)) {
touch($file);
// do stuff
}
time() gives you the current time in seconds. You should probably unroll 60 * 15 to 900, I just provided it with both numbers to illustrate what was going on.
Also, a file might be better for this than a database table. Have a look at the touch()
function. It changes the modification time of a file, or creates an empty file with the current time as the mod time if it doesn't exist. You can check the file mod time with filemtime()
<?php
$lastUpdated = null;
$file = '/path/to/writable/file/with/nothing/in/it';
if (file_exists($file)) {
$lastUpdated = filemtime($lastUpdated);
}
if (!$lastUpdated || (time() - $lastUpdated) > 900) {
touch($file);
// do stuff
}

You seem to use MySQL as the DBMS. In that case and if you want you can let MySQL do most of the work:
SELECT
pit < Now()-Interval 15 Minute as mustUpdate
FROM
last_updated
WHERE
siteId=?
pit is your DateTime field and siteId is some condition you may have if you store more than one record in the table (which sounds like a good idea to me).
The result (if there is such a record with siteId=?) contains a field mustUpdate which either contains 0 or 1, 1 indicating that the value of pit is more than 15 minutes in the past.

Related

Time Calculations with MySQL

I'm writing a time logging programme for a client who is a piano tuner, and I've written the following PHP code to give a record a status of 'to do':
$last_tuned = '2017-01-05';
$tuning_period = 3;
$month_last_tuned = date('Y-m', strtotime(date('Y-m-d', strtotime($last_tuned))));
$next_tuning = date('Y-m', strtotime($month_last_tuned.(' +'.$tuning_period.' months')));
if (time() > strtotime($next_tuning.' -1 months')) {
if (time() > strtotime($next_tuning)) {
return 'late';
} else {
return 'upcoming';
}
}
As you can see, the $last_tuned variable is of the date(YYYY-MM-DD) format. This is then converted to a (YYYY-MM) format.
Once convered, an additional number of months, identical to $tuning_period is then added to the $month_last_tuned variable giving us a month and year value for when we need to add a new record.
If the current time (found with time()) is greater than the $next_tuning variable - 1 month, it returns that the task is upcoming. If it's after the $next_tuning variable, it returns that the task is late.
I now have to write a MySQL query to list the items that would return as upcoming or late.
How would I write this in MySQL? I'm not very good with MySQL functions, and some help would be much appreciated.
My attempt at the logic is:
SELECT * FROM records
// The next lines are to get the most recent month_last_tuned value and add the tuning_period variable
WHERE
NOW() > (SELECT tuning_date FROM tunings ORDER BY tuning_date ASC LIMIT 1)
+
(SELECT tuning_period FROM records WHERE records.id = INITIAL CUSTOMER ID)
I know that that is completely wrong. The logic is pretty much there though.
My database schema is as follows:
I expect the rows returned from the query to be on-par with the 'late' or 'upcoming' values in the PHP Code above. This means that the rows returned will be within 1 months of their next tuning date (calculated from last tuning plus tuning period).
Thanks!
You'd probably be better off with using the DateTime object instead of manipulating date strings.
$last_tuned = '2017-01-05';
$tuning_period = 3; // months
$dt_last_tuned = DateTimeImmutable::createFromFormat('Y-m-d',$last_tuned);
$dt_next_tuning = $dt_last_tuned->add(new DateInterval('P3M'));
$dt_now = new DateTimeImmutable();
$dt_tuning_upcoming = $dt_next_tuning->sub(new DateInterval('P1M'));
if( $dt_now > $dt_next_tuning) {
return 'late';
}
if( $dt_now > $dt_tuning_upcoming) {
return 'upcoming';
}
You can also use these DateTime objects in your MySQL queries, by building the query and passing through something like $dt_next_tuning->format('Y-m-d H:i:s'); as needed.
Given your table structure, however, it may be easier to just get all the relevant records and process them. It's a little difficult to tell exactly how the pieces fit together, but generally speaking MySQL shouldn't be used for "processing" stuff.

MySQL Event history, find each row within 5 minutes of previous, until no row is found

I have a database containing a table of objects (network devices) and an event table, containing timestamps of when they couldn't be reached via ping. The table does not have any information on when they COULD be pinged, only when they were unreachable.
To calculate "down time" I made a php script that gets any even that is within n seconds of the previous event row for that object. The script ends up being ~50-100 separate queries, and I'm not sure how to fit this into one SQL query.
Any help is appreciated!
function GetDownTime(PDO $sql, $Objid) {
$DownChain=array();
$Last=null;
$i=1;
while($Last!==False) {
try {
// Select the down timestamp for the correct object
// where down is LESS THAN the last down pulled (or current time if this is the first attempt)
// where down is not greater than or equal to expired
// expired is the last timestamp minus 600 (10 minutes). - this means we wont grab timestamps after a 10 minute gap (uptime)
$GetEvent=$sql->Prepare("SELECT down,UNIX_TIMESTAMP(down) as unix FROM events
WHERE obj_id=:objid
AND UNIX_TIMESTAMP(down) < :last
AND UNIX_TIMESTAMP(down) >= :expired
ORDER BY down DESC
LIMIT 1");
$GetEvent->Execute(array(
':objid' => $Objid
,':last' => ($Last ? $Last : time())
,':expired' => $Last-(DOWNTIME_MAXHOPSIZE ? DOWNTIME_MAXHOPSIZE : 600) // If for any reason the function can't get the constant value then default to 600
));
} catch (PDOException $e) {
die($e->getmessage());
}
if($GetEvent->RowCount()==1) {
// Event found
$Event=$GetEvent->Fetch(PDO::FETCH_ASSOC);
$Last = $Event['unix'];
$DownChain[] = $Event['unix'];
} else {
// Event not found
$Last=false;
}
$i++;
}
/* etc etc */
}
This aligns with approach noted by #JohnMcMahon in comments. Don't limit the result set, just pull one row in at a time (i.e. iterate the DB rows), and stop your loop from reading out records once you find a record that breaks your condition. No need for complex query at all here.

How would I go about timing between status changes in php?

When the status changes to prepare/preparing, the timer begins. I then want to stop the timer and calculate the difference when the status changes to ready, and store it as time in the database. Ive tried various ways but can't seem to get it working, what am I doing wrong? Thanks
if(isset($_POST['prepare'])){
$_SESSION['startTime'] = time();
$question2="UPDATE `order` SET orderStatus='Preparing', idEmployee='$_SESSION[id]' WHERE idorder='$_POST[id]'";
$sth = $db->prepare($question2);
$sth->execute();
}
if(isset($_POST['ready'])){
$total = time() - $_SESSION['startTime'];
echo date('h:i:s', $total);
$question2="UPDATE `order` SET orderStatus='Completed', timeCompleted='$total' WHERE idorder='$_POST[id]'";
$sth = $db->prepare($question2);
$sth->execute();
}
edit: I overcame the issues I was having by simply using a method within the DateTime class. I began by recording the time from when the order was taken, I also recorded the time of when the order was completed. I then used the method diff() to calculate the difference between the 2 recorded times and stored the results in my db.
if(isset($_POST['prepare'])){
$_SESSION['startTime'] = new DateTime();
$question2="UPDATE `order` SET orderStatus='Preparing', idEmployee='$_SESSION[id]' WHERE idorder='$_POST[prepare]'";
$sth = $db->prepare($question2);
$sth->execute();
}
if(isset($_POST['ready'])){
$endTime = new DateTime();
$i = $_SESSION['startTime']->diff($endTime);
$end = $i->format('%h:%i:%s');
$question2="UPDATE `order` SET orderStatus='Completed', timeCompleted='$end' WHERE idorder='$_POST[ready]'";
$sth = $db->prepare($question2);
$sth->execute();
}
Replace $total = time() - $_SESSION['startTime'] with $total = time() - strtotime($_SESSION['startTime'])
And add session_start(); to the top of your code if you didn't
Then it will work.
If both prepare and ready are actioned on the same machine by the same person (within the same session) - this code should work. If you believe all this to be true - I would check to make sure the session variables are being set print_r($_SESSION)
However, I would recommend when you update orderStatus to 'Preparing', creating a new column called timeStarted and update that to time(), then when you are updating to 'Completed' set timecompleted also to time()
You can then easily work out the difference, as currently (if this code did work timeCompleted is actually timeTaken) - for which you could even add a 3rd column which is the difference between the two for easy reporting.
Doing it this way means if it takes longer than the session or the computer restarts / re login the startTime is not lost

How to detect that time is past midnight?

Im coding a text-based mafia game in norwegian and need help with time detection. So here's the deal. In way to delete a mysql-record if time since a player bought the product is over midnight (24 hours clock). Here is what I tried, but in unsure it's the best method:
// Har livvakt? (Has bodyguard)
if($this->isTheftProtected($user_id)){
$sql = mysql_query("SELECT * FROM `UserTing` WHERE t_meta = '2' AND t_owner = '".$user_id."'");
$rows = mysql_fetch_array($sql);
$timeThen = date("Hi", $rows["t_time"]);
$theNow = date("Hi");
if($timeThen > 0000){
// Slett produktet <- Delete here... past midnight.
} else {
// Behold.
}
} else {
return;
}
So, is there a better way. Should time() be considered to be used? Its really how to do this that my question is.
Regards. ;)
You might need to add cronjob or just run this query before SELECT to delete old records.
DELETE FROM `t1` WHERE DATE(`created`) < CURDATE();
JOINS also can be used...
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestampdiff
mysql> SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');
Returns 128885
So logically;
SELECT * FROM UserTing WHERE TIMESTAMPDIFF(SECOND, NOW(), t_time) >= (60 * 60 * 24) AND t_owner = {$user_id}
Shows values that 24 hours older than the current time, for t_owner.
Edit 3: Make sure you are always using MySQL time comparisons with MySQL, or PHP. But not both, as there is a allowed time variance allowed between the two. (They can sometimes be off by as much as a hour with no errors.)

Sql select query (return results that are 120 seconds less than current time

This script worked just fine on my old server with php 4 compatibility. I moved to a new server that's php 5 only and it's not working please help. The script returns a list of members currently online, if the current time is no more than 120 seconds greater than their last activity time. The last activity time is updated every few seconds by another script as a timestamp (eg: 1308421786).
function getTimeStamp() {
return time();
}
//Who's Online
$query_omoline = "SELECT * FROM ttourmember WHERE '".getTimeStamp()."'-`chatactive` <120 AND `chatactive`<>0 ORDER BY membername ASC";
$omoline = mysql_query($query_omoline) or die(mysql_error());
$row_omoline = mysql_fetch_assoc($omoline);
$totalRows_omoline = mysql_num_rows($omoline);
script then returns the results like this
<?php do { ?>
<?php
$omemname=$row_omoline['membername'];
$omemid=$row_omoline['memberid'];
if($totalRows_omoline>0){ ?>
<?php echo $row_omoline['membername']; ?>
<?php }} while ($row_omoline = mysql_fetch_assoc($omoline)); ?>
try adding true to the time call time(true). That way it converts the result to a float, which can be used for arithmetic operations. I am not sure if that's the problem here, since the operation is done in SQL-land, but its worth a try.

Categories