Adding time parts of an database result? - php

I'm trying to add a feature in my application that totals how much time a user spends in the system by the week, month, etc.
$select = "SELECT TOTAL_HRS FROM timeclock WHERE USERNAME = '$sessuser' AND CLOCK_OUT BETWEEN '$dbpast' AND '$dbnow'";
I have a MySql result of two sample time entries: 00:00hr:04min:08s and 00:00hr:12min:52s. Users can have more.
TOTAL_HRS is a varchar column, so when I put a sum() on it, it returns a 0.
Here's what I have so far:
while($row = $query->fetch_assoc()){
print_r($row);
$sanitized = preg_replace("/[^0-9:]+/", "", $row);
print_r($sanitized);
$joinarr = implode(':', $sanitized);
$parts = explode(':', $joinarr);
print_r($parts);
$zerodate = new DateTime('0000-01-01 00:00:00');
$addhrs += $parts[1];
$addmin += $parts[2];
print_r($addhrs);
$interval = $zerodate->add(new DateInterval('P' .$parts[0].'DT'.$parts[1].'H'.$parts[2].'M'.$parts[3].'S'));
$totalhrs = $interval->format('%D:%Hhr:%Imin:%Ss');
print_r($totalhrs);
}
I get funky junk in return: 0%Sat:%0012Sat, 01 Jan 0000 00:12:52 +0100:%001121:%st52
What I need to return back is: something like: 00:00hr:17min:00s. I don't plan on storing this, just want it to display on a page.
I need some help figuring this out. I'm sure there is a better way. I'm not that great at functions. Or should I send the results through jquery and handle them there? Which side is more efficient at handling DateTime? The help would be much appreciated. Thanks!

You can calculate the number of seconds between two datetime values using TIMESTAMPDIFF() and then sum that. e.g.
SELECT SUM(TIMESTAMPDIFF(SECOND,CLOCK_IN,CLOCK_OUT)) AS TOTAL_SECS
FROM timeclock
WHERE USERNAME = '$sessuser' AND CLOCK_OUT BETWEEN '$dbpast' AND '$dbnow'
see: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestampdiff
You might currently be using TIMEDIFF() which gives you those "funky" values

I would do it like this:
Create a column in the database to save each session time on site. I would probably set it as an integer rather than a timestamp column. I just need it to return a number. I'd have a separate timestamp column to record the time of the visit.
Client side bind a javascript/jquery function to window.onload which saves to localstorage / sets a cookie to current timestamp when the page is loaded, use moment.js library to display total site time to user and have it count up in real time. Check to see if cookies already exist and if so process them before setting new values.
Either bind another function to window.onunload to save another cookie with the timestamp when the user navigates away from the site, or use setInterval to save the latest timestamp every minute or so while they are on the site.
On page load check if cookies/localstorage have values then subtract timestamp of page load from timestamp of page unload to get number of seconds they spent on site. Save that to database and use the timestamp of the unload event to set the timestamp of their visit.
Run relevant queries on the database to return total seconds on site in last day/week/month whatever and pass them to moment.js via ajax. It can displaying a counter like you describe from a string containing a value in seconds using about 2 lines of code.

Related

How to calculate the total time logged in the system?

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

Use of timestamp from database in jquery

I am trying to run a counter from the time user is entered into database
I got this fiddle
http://jsfiddle.net/brkp1sa2/
which starts timer from 08/24/2012 while i need to start it from user date which i enter into database as timestamp at the time of signup
How I can do it as I fetch val from database like
<?php $timd = $db->fetchVal("select ts from users where id = ?", $id);
if (!empty($timd)) {
$timdl = $timd->ts;
}
Not know php pr jquery much so a code example answer can help me better
How to use this value into jquery so time start from given time stamp
Javascript timestamps are Javascript numbers representing Unix time in milliseconds. MySQL uses its UNIX_TIMESTAMP() function to generate Unix timestamps (in seconds) from various kinds of date / time datatypes.
So, the query
select UNIX_TIMESTAMP(ts) * 1000.0 AS ts from users where id = ?
will generate a Javascript timestamp value.
Now, Javascript timestamps and Unix timestamps are, by design at least, in the UTC time zone. Depending on how your table's ts values were stored, your results may come out in local time.

How to set the current time as static variable using PHP?

I need to set the current date and time in static variable.
I need to insert the 50 records into database table. Here,I need to insert the current date and time. Then, I need to set the current date and time of the 50 records are same. I used this date('Y-m-d H:i:s'); format. This format will change every minutes and seconds.
How to I do. Please help me.
$date = date('Y-m-d H:i:s')
then use this variable,for create records. All records will have same time.
It's been a long time, but I found a simple solution. Maybe it's useful for someone (like me) that wants to do the same thing nowadays.
Even when you store the current time/datetime to a variable, the time it's still running, so it changes every second.
I solved it by storing the time() value into a MySQL table (datetime type of course), so the captured time will be stored as it is and stop running and changing every second. Then, when I want to use it, I just make a query from the MySQL table.
It's a simple way (for me) to capture the "now" value and make it stop running, but maybe there's a better way.

Inserting actual hours (not time) to MySQL

I am trying to insert actual hours not the time itself to MySQL database through form fields. So for example
$time1 = '00:00';
$time2 = '27:20';
$time3 = '00:45';
So I can retrieve the different rows and can calculate on the fly whenever require. Either through search query or even in other area of the system.
When I have tried to do addition of above three times, it is not giving the result the way I am looking for
$total = strtotime($time1) + strtotime($time2) + strtotime($time3);
echo date('H:i:s', $total);
The result
14:16:44
While it should be something like
28:05:00
I have used TIME DATATYPE in MySQL table. I may use as a TEXT but I am also concern about the error happen in user input. Where I do not have to force the user to insert the any particular format but they can either insert as below way
27.20
27:20
or
1.5
1:30
My main concern is to calculate the time, the user input can be on second priority but it would be great if can implement.
So is there anyway, idea or hint to achieve this?
date() expects the timestamp in UNIX format, i.e. seconds since January 1 1970 00:00:00 UTC (which is also the value provided by strtotime)
You're passing it the result of adding a series of amounts of time since 1 January 1970 instead of just adding up hours, so (as far as date is concerned) you're generating a random date and time, and printing only the time (try printing the date of $total and see what you get).
Since your time is stored in the database, one possibility is to let MySQL handle the time calculations itself, e.g.:
SELECT ADDTIME('00:00',ADDTIME('27:20','00:45'))
will result in "28:05:00". You can have your database fields as TIME and operate on them directly through SQL, and do the user input conversions into acceptable TIME values in PHP.
If you're only interested in the hours and minutes, why don't you just store the value as an in integer? Just multiply the hours by 60.
You can handle the conversion in PHP.
Alternatively, you can also easily use two (very small) int fields for this.

PHP Foreach Loop Query

I've been tinkering with PHP lately (self-taught, no formal training), trying to understand how to grab data from a database and display the data somewhere. So far I have learned quite a bit, but now I am stumped.
I have a list of about 200 users in my local database in a table called site_members. The table has three fields: id, name, birth_date. Via PHP, I want to display all the users on a webpage, and have something like "Birthday soon!" be mentioned right after their name. Something like this:
John Smith (Birthday soon!)
I haven't written the code to do this, because I usually write pseudocode first before actually diving into the coding part. Here's the pseudocode:
Get the current date and time and convert it to Unix timestamp
Start foreach loop and go through list of users
Query the database table, get the birthdate of a user by their id, and store it in a variable named bdate.
Convert bdate to Unix timestamp
Subtract the current date from bdate, convert it into days remaining, and store it in a variable called remaining_days.
If the user's bdate is within 15 days (remaining_days is less than 15)
Display their name, followed by (Birthday soon!)
otherwise
Just display their name only
End if
End foreach loop
Here's my problem: With the above pseudocode once translated into actual code, there would be a database query made every time in that foreach loop. Some of the tutorials I consulted mentioned I should avoid that for efficiency reasons, and it makes sense. I ran Google searches to find something similar, but that didn't do much. I do not want anyone to write any actual code for me. I just want a better solution to the querying.
Thanks in advance!
I think your concept for the pseudo code is right, and you're understanding of doing multiple database queries is also right, you just tangled the two into giving you a wrong idea.
If you construct your select statement properly (that's basically what you'd be using to access the database), you actually pull the information for everyone out of the database and store it once in an array (or some other form of object). You can then start your foreach loop using the array as your value and perform the rest of your checks that way.
$date = date("m.d.y");
$people = ** insert your commands to grab the info from the DB **
foreach($people as $person) {
// do your comparison checks and echo's etc in here
}
Does this make sense?
There can be two solutions to your problem:-
1:
Instead of making query for every user, first get the data for all the users.
Traverse the data using foreach loop php
Do the processing and display the results.
2:
Store the user date_of_birth in proper mysql date datatype
Change your mysql query to use date function to get all the users who match your date difference criteria and just display those users.
It seems you failed to read up properly on the relationship between SQL and PHP. If you actually posted code, then you could have been easily unstumped because there are many ways to do the simple task from legacy tutorials to current PDO or even MVC within in 5mins or less.
I'm not going to write the code but you need to change HOW you think in your "pseudo code".
The problem with your pseudo code is because you believe that the DB is not smart and you are doing it as if it was only for storage.
The correct pattern for PHP is the following:
1) use the Date function to retrieve current day + 15. Get month and
day only.
2) you make a SQL query that retrieve all users who's
birth_date field's month and day are GREATER THAN (or equal) to
TODAY and who are less than or equal to today + 15 (day and month
only)
3) execute the query.
4) with the returned data set (if any)
you can choose two path depending situation and design
a) you can loop it with a simple FETCH which fetch each row retrieve
and display name and extra message.
or
b) iterates through the result set and store the display message
into a variable and then finally display it once the iteration is
done.
(option b is prefered because its more flexible since you can use this technique to out into a file instead of an echo)
THIS pseudo-code ensures that you are only retrieve the correct data set with the aid of the SQL system (or storage system).
In terms of overall process, aashnisshah is absolutely correct. First, you should retrieve all the records you need from your database then loop through each row to do your data comparisons and finally close the loop.
As for finding out if their birthday is close and if you want MySQL to do the hard work, you can build your query like that in PHP:
$query = "SELECT *, DATEDIFF(DATE_FORMAT(dob, '" . date('Y') . "-%m-%d'), CURDATE()) AS days_to_dob FROM Members";
The idea is to fetch an extra column called 'days_to_dob' containing the amount of days until that person's date of birth. Note that it will be negative if that date has passed for this year. With that extra column you can easily evaluate whether their dob is within 15 days.
If you don't want any php code, then here is my pseudocode:
Get date and time -> UTC stamp and store in $time_current
Get all from site_members and store in $data
for each entry in $data, store in $record
get birth_date from $record and convert to utc stamp and store in $birthday
print name from $record
if $birthday is close to $time_current then print "Birthday soon" end if
print new line
end for
That performs only one request to your database.

Categories