How to calculate the total time logged in the system? - php

I am using CodeIgniter and I am calculating the total time from the dates.
Explanation:
What I am doing is, Every login I am inserting the last_Ativity date and time in the database using below code.
$data_login= array('emp_id' =>$result->id ,'last_activity' =>date("Y-m-d H:i:s", STRTOTIME(date('h:i:sa'))));
$this->db->insert('tbl_current_login',$data_login);
last_activity time continuously updating if the user still in the system . (I am using ajax to update the datetime. I haven't shared that code).
Now I have to calculate the total time of the specific user for a single day(current date).
For example- emp_id 26 logged in twice so I have to calculate the time
First-time login date and time:-2018-09-17 07:27:55
Second-time login date and time:- 2018-09-17 07:35:22
It will increase depending upon how many time the user logged in.
I am confused about the time. Am I on the right path to calculate the total hour login in the system?
Should I use an MYSQL query or PHP to calculate? I need some idea.
Would you help me out in this?

This is what I would do
last_activity time continuously updating if the user still in the system . (I am using ajax to update the datetime. I haven't shared that code).
Before you update the row.
check if a row for activity exists
if it does, get the timestamps for the date and subtract the current time (the one you are changing last_activity to, from the one stored in the DB) take that number and add it to an integer column named something like elapsed time (you would have to add this to the DB)
if not then enter a row with 0 elapsed time ( depending how you put the first row in, maybe on login) this may never be an issue.
For the timestamps, you would do a select to get the current row. Take the datetime field and use either
$time = strtotime($row['last_activity']);
OR
$time = (new DateTime($row['last_activity']))->getTimestamp();
Then you simply do the same thing to the date you are going to replace that with and then subtract to get the difference in seconds.
$elapsed = time() - $time;
And then add that to the current rows value, and save it. This way you can keep track of a running total in seconds of the time they spend during that session.
Then when you need to count the total time its a simple matter of doing
SELECT SUM(elapsed_time) FROM {table} WHERE DATE(last_Ativity) = :date
If you were dealing with just two date time fields in the DB it would be easier to just get the difference of those, but sense you already have code to constantly update the last active field this would require less work in the long run IMO.
Option2
The other option is to add another Datetime field to put a start time or login time in. Then when you query you can convert them to their timestamps and subtract to get the difference.
This makes the SQL harder (when doing the SUM ), I can't really think off the top of my head how I would calculate the elapsed time on multiple rows and then sum them up. But it does simplify the PHP quite a bit. So which ever way works best for what you need. Think about if you need the utility to know when they logged in, or if you just want an easier way to calculate the time they spend.
Something like that.

Assuming that the only log happens based on user actions, and so, after 15 minutes (for example) the user is assumed logged out
And assuming you'd want daily total, the solution should be something like this:
SELECT
first.emp_id,
SUM(TIMESTAMPDIFF(MINUTE,first.last_acivity, DATE_ADD(IFNULL(last.last_acivity, first.last_acivity), INTERVAL 15 MINUTE))) as logged_minutes
FROM
(
SELECT
la1.*
FROM
last_acivity la1
LEFT JOIN last_acivity la2 ON
la1.emp_id = la2.emp_id AND la1.last_acivity < la2.last_acivity
AND la2.activity =< #date0
WHERE
la1.last_acivity >= #date0
AND la2.login_id IS NULL
) first
LEFT JOIN
(
SELECT
la1.*
FROM
last_acivity la1
LEFT JOIN last_acivity la2 ON
la1.emp_id = la2.emp_id AND la1.last_acivity > la2.last_acivity
AND la2.activity =< #date0
WHERE
la1.last_acivity >= #date0
AND la2.login_id IS NULL
) last
ON
first.emp_id = last.emp_id
GROUP BY
emp_id
In this query need to set the date seperately:
SET #date0 = DATE(NOW()) ;
To get the first record of the day, or the last, we need to LEFT join the table to itself, on the same emp_id BUT witn with an inequality, which will get for each emp record its ancestors or predecessors
When we add the NULL condition we bring the we get the edge case: first or last
What's left then is just calculating the minutes between the 2 tables
Since I assumed no log out record occurs, I treated the case when the first and last logins are the same, or no last login

Related

How to add 1 hour to a queried time from the database?

I'm a beginner for php and developing this web application, which users who registered on this site, can be claimed some scores in every one hour. When a user claims at some time, database stores that time as time data type in to user_claim_time column. When that same user tries for his next claim, this php script be able to get his last claim time and add one hour to check if the user really claims in an one hour.
So, my question is how can we add one hour to queried time. I'm using php time(h:i:s) function to store server's current time into the database.
You can do something like this:
SELECT * FROM your_table
WHERE user_claim_time < NOW() - INTERVAL 1 HOUR
However i recommend you to use user_claim_time column in datetime format.
Because time like this '00:00:00' will produce negative output as one hour subtraction can change the date or month as well. For example date like this '2017-08-01 00:00:00'.
So using datetime is the right way i think to properly compare time difference.

MySQL get one more result out of time range

I'm making a PHP based site designed to display line graphs based on data over time. Where the user selects a time range and gets a graph corresponding to what was selected.
The problem is that to calculate any given point, I need to know the previous record. I have no way of knowing when it was, it may have been an hour or a week before hand, but it could have been a minute.
So is there anyway, from within SQL, to specify a time range and one record before that?
You can do another query that gets the last record before the time range:
SELECT *
FROM yourTable
WHERE time < #start_time
ORDER BY time DESC
LIMIT 1
You can combine this with the original query using UNION.

PHP Script to Add One Every Hour

I'm new to PHP and I'm hoping to make a script where a user will get a "coin" every hour that they go on the page. For instance, if a user logs in twice during the same hour, they will only get one coin. But if they refresh the page during the next hour, they get another coin. However, they do not get coins when they do not refresh the page, even if many hours go by.
How would I even start going about doing this? Any help would be extremely appreciated.
Easy... :) If you are using MySQL or something to store the coins, get the time too, when the coin was credited. And each time the page is called, check the time. A pseudo code would be like this:
load(coins);
timeDiff = timeNow - timeLastCredited;
if (timeDiff > 1 hour)
coins++;
save(coins);
In case of PHP, I guess you may do like this:
$coins = getCoins(); // Assuming this function will load the current coins count from DB.
$lastCredit = getLastCoinCreditedTime(); // Should return a DateTime integer.
$timeDiff = microtime() - strtotime($lastCredit);
if ($timeDiff > 60*60*60*1000)
saveCoins($coins+1); // Assuming this function saves the new number of coins.
I'd do it this way:
On each page load (refresh, login, whatever), check to see if the user has already received a coin for the current hour. To do this, you need to know what the current hour is:
$hour = (new DateTime())->format("Y-m-d-h");
This will give a value like "2013-03-25-11" during the 11:00 hour. I'm including the date, since we don't to want skip giving a coin in, say, the 11 o'clock hour just because they were online yesterday at 11:05.
Then you can either:
Add one to their coin total whenever you have a new $hour value (ie. it's not recorded in your database) and save the $hour value, or
Save the $hour value in the database and count the total number of coins earned with a query like SELECT COUNT(DISTINCT hour) FROM table;
The first approach is useful if they're spending the coins on something (ie. you can add/subtract from their "coin account"); the second is useful if you just want a grand total of the number of coins (ie. the total number earned, ever).
I'm going to assume that you have a users table in a database.
If that is the case, you can use a column in the database to update the latest time that a user has gone on the page with php and a query on that page. Then you can set up a cron job that runs every hour that will query the users table and see if the user has viewed the page within the last hour. If the user has viewed the page within the last hour, increment the amount of coins associated with that user.

MYSQL Group By date + 3 hours

I have a query that counts the "Xp" difference per day from my database, this all works as it should however it groups from midnight-midnight, what I would like to do is group 3am to 3am.
However another issue I think I may have is that my query may not always have the rows being the exact second at 3am due to the fact that it has to run a huge query and retrieve data from another website per user profile, so it should get all data after 3am, but before maybe 4am or something, so it has enough time to get all of the rows.
my current mysql is:
SELECT FROM_UNIXTIME(date, '%Y%m%d') AS YYYYMMDD, MAX(xp)-MIN(xp) AS xp_gain
FROM skills
WHERE userID = '$checkID'
AND skill = '$skill'
AND date >= '$date'
GROUP BY YYYYMMDD
ORDER BY date ASC
The best way to handle this is to add (if you can) another column that is just a DATE (not a DATETIME) and have this field rollover from one day to the next at 3am, (you can to this by subtracting 3 hours from the current time when doing the INSERT).
This gives you a couple of benefits, especially with a large number of rows:
It is much faster to query or group by a DATE than a range of
DATETIME
It will always query the rows at the exact second of 3am,
regardless of how long the query takes.

count mysql values for the week and then start count again from monday?

i have a count query that counts how many times a user has viewed another users profile.
It currently just counts all the rows in the table, however i was wondering if there was a way in php to use a calculation that says count all rows in the table 'ptb_profile_views' from monday to sunday and then start from 0 again on the following monday and count all the values for that week and do not include any counts from the previous week, im not sure this is possible thought because it would need some time of memory aspect behind it,
the other option i was wondering is whether theres a mysql statement that i can add to say every sunday at 00:00AM delete all from ptb_profile_views and then we start fresh for monday.
can someone please help me with any sort of solution, thanks
my table looks like:
id | profile_id | viewed_id
1 4 8
2 5 6
mysql
function check_profile_views() {
global $connection;
global $_SESSION;
$query = "SELECT COUNT(DISTINCT profile_id) totalCOUNT FROM ptb_profile_views WHERE viewed_profile_id=".$_SESSION['user_id']." AND profile_id!='-1'";
$check_profile_views_set = mysql_query($query, $connection);
confirm_query($check_profile_views_set);
return $check_profile_views_set;
}
php
<?
$check_profile_views_set = check_profile_views();
while ($views = mysql_fetch_array($check_profile_views_set)) {
echo"".$views['totalCOUNT'].""; } ?>
You can filter by day-of-week, week-of-year, e.g.
SELECT count(*), YEAR(datefield), WEEK_OF_YEAR(datefield)
FROM yourtable
GROUP BY YEAR(datefield), WEEK_OF_YEAR(datefield)
the deletion logic would be similar. delete all records in this year that have a week-of-year earlier than "this week", and then also delete all records from previous years:
DELETE FROM yourtable
WHERE (YEAR(datefield) < YEAR(now()))
OR (YEAR(datefield) = YEAR(now()) AND (WEEK_OF_YEAR(datefield) < WEEK_OF_YEAR(now()))
since you mentioned you don't keep a history with datetimes for everytime someone visits a profile but just count, the only solution is to reset you counters every monday at 00:00.
You can do this with a cron job. You should be able to create one from your hosts admin panel.
Alternatively you could run the cron-page yourself manualy every monday to reset the counters.
If you would like to make things more complicated, you could have the cron-page create/update a log file where you keep the total visits.
The best solution, however, would be to rethink your database design and create a table that nicely logs each visit with the right datetime.

Categories