PHP MySql time calculations - php

I want to calculate how much time the worker has left since break start.
By the click, PHP insert into history table a record with timestamp (break_start), after second click, PHP update record with timestamp (break_end).
Now i can calculate time difference using this code:
$break_start = $worker->query('SELECT break_start FROM history WHERE id = 16')->fetchArray();
$break_end = $worker->query('SELECT break_end FROM history WHERE id = 16')->fetchArray();
$diff = $worker->query("SELECT TIMEDIFF('".$break_end['break_end']."','".$break_start['break_start']."') AS total")->fetchArray();
$break_total = $worker->query("SELECT break_time FROM worker WHERE id = 7")->fetchArray();
echo $diff['total']." ";
echo $break_total['break_time']." ";
$str1 = strtotime($diff['total']);
$str2 = strtotime($break_total['break_time']);
Output is: 00:31:26 00:30:00.00 86 01:26
(This code above is just attempt to understand time in PHP and MySQL).
I want to subtract break time from "break" value which is stored in table "worker" (default value is 30).
I don`t know how to do this..

Related

Unable to generate sequence wise unique number along with day in PHP

in my code I have a product uploading system, I want every time I upload a product it would have a unique product code.I'm using PHP CodeIgniter framework. I've done everything e.g the end two digits of the year and the count of days out of 365 days but unable to generate serial number like 1865001 then 1865002 then 1865003.
Below is the code of my controller
public function view(){
$data['subview'] = 'admin/parts/user_list';
$data['title'] = 'User Overview';
$data['users'] = $this->Users_model->get_users();
//Code Generator
$this->load->helper('string');
$y= substr(date('Y'),2);
$t = date('z') + 1;
$data['codes'] = $y.$t;
$this->load->view('admin/__layout_admin.php', $data);
print_r($data['codes']);
}
The current output is 1865.
I want it should be like 1865001,1865002,1865003,1865004.
Please help me doing this.
First of all, numbers should be like 18065001, note the zero between 18 and 65, cause when you reach day 100th you will keep the length.
Also, you will need a daily counter to generate sequential part (001, 002, ..), I would store that counter in a database so u can update every time u generate a product and reset it when a new day coming up.
So the code could be something like:
public function view(){
$data['subview'] = 'admin/parts/user_list';
$data['title'] = 'User Overview';
$data['users'] = $this->Users_model->get_users();
//Code Generator
$this->load->helper('string');
$y= substr(date('Y'),2);
$t = date('z') + 1;
// fill one one zero if year is less than 100
$t = 2 == strlen($t) ? '0' . $t : $t;
$counter = $this->ProductCounter_model->get_counter();
$data['codes'] = $y . $t . sprintf('%03d', $counter + 1);
$this->load->view('admin/__layout_admin.php', $data);
print_r($data['codes']);
}
So in $data['counter'] you will receive the current counter and when you store the product you should update the counter in the database. Don't forget to reset the counter to zero at midnight.
And if it is not strictly necessary to have correlative numbers (001, 002, 003) I will use the number of seconds from midnight which would simplify the process and avoid to save and reset the counter and also pass it as a parameter in data, in that case, you can change this line:
$data['codes'] = $y . $t. sprintf('%05d', echo time() -
strtotime("today"));
You need 5 space for the greatest number of second from one day, 86400 seconds.

2D PHP array, join values based on similar values

I have PHP array which I use to draw a graph
Json format:
{"y":24.1,"x":"2017-12-04 11:21:25"},
{"y":24.1,"x":"2017-12-04 11:32:25"},
{"y":24.3,"x":"2017-12-04 11:33:30"},
{"y":24.1,"x":"2017-12-04 11:34:25"},
{"y":24.2,"x":"2017-12-04 11:35:35"},.........
{"y":26.2,"x":"2017-12-04 11:36:35"}, ->goes up for about a minute
{"y":26.3,"x":"2017-12-04 11:37:35"},.........
{"y":24.1,"x":"2017-12-04 11:38:25"},
{"y":24.3,"x":"2017-12-04 11:39:30"}
y=is temperature and x value is date time,
as you can see temperature doesn't change so often even if, it change only for max 0.4. But sometimes after a long period of similar values it change for more than 0.4.
I would like to join those similar values, so graph would not have 200k of similar values but only those that are "important".
I would need an advice, how to make or which algorithm would be perfect to create optimized array like i would like.
perfect output:
{"y":24.1,"x":"2017-12-04 11:21:25"},.........
{"y":24.1,"x":"2017-12-04 11:34:25"},
{"y":24.2,"x":"2017-12-04 11:35:35"},.........
{"y":26.2,"x":"2017-12-04 11:36:35"}, ->goes up for about a minute
{"y":26.3,"x":"2017-12-04 11:37:35"},.........
{"y":24.1,"x":"2017-12-04 11:38:25"}
Any help?
As you specified php I'm going to assume you can handle this on the output side.
Basically, you want logic like "if the absolute value of the temperature exceeds the last temperature by so much, or the time is greater than the last time by x minutes, then let's output a point on the graph". If that's the case you can get the result by the following:
$temps = array(); //your data in the question
$temp = 0;
$time = 0;
$time_max = 120; //two minutes
$temp_important = .4; //max you'll tolerate
$output = [];
foreach($temps as $point){
if(strtotime($point['x']) - $time > $time_max || abs($point['y'] - $temp) >= $temp_important){
// add it to output
$output[] = $point;
}
//update our data points
if(strtotime($point['x']) - $time > $time_max){
$time = strtotime($point['x']);
}
if(abs($point['y'] - $temp) >= $temp_important){
$temp = $point['y'];
}
}
// and out we go..
echo json_encode($output);
Hmm, that's not exactly what you're asking for, as if the temp spiked in a short time and then went down immediately, you'd need to change your logic - but think of it in terms of requirements.
If you're RECEIVING data on the output side I'd write something in javascript to store these points in/out and use the same logic. You might need to buffer 2-3 points to make your decision. Your logic here is performing an important task so you'd want to encapsulate it and make sure you could specify the parameters easily.

Date insertion in Cassandra DB: non-trivial 1h shift issue

I am a bit desperate about this problem... I have no idea how to face it.
Here is a simpler way to look at this problem:
If my insert cql query is:
"BEGIN BATCH USING CONSISTENCY ONE insert into my_table(id,'2014-04-11 8:00:00',...,'2014-04-15 10:00:00') values ('2036548',3.15,...,4.11) APPLY BATCH"
...and my data request cql query is:
"Select FIRST 100000 '2014-04-01 0:00:00'..'2014-04-16 0:00:00' from my_table where id=2036548"
...why does the inserted date 2014-04-15 10:00:00 changes to 2014-04-15 11:00:00 when pullling it from Cassandra?
The date pulling code in vb.net is:
Public Shared Function getCassandraDate(ByVal value As Byte()) As Date
Dim buffer As Byte() = New Byte(value.Length - 1) {}
value.CopyTo(buffer, 0)
Array.Reverse(buffer)
Dim ticks As Long = BitConverter.ToInt64(buffer, 0)
Dim dateTime As New System.DateTime(1970, 1, 1, 0, 0, 0, _
0)
dateTime = dateTime.AddMilliseconds(ticks)
Return dateTime.ToLocalTime
End Function
...same thing in PHP:
date_default_timezone_set("Europe/Paris");
$time = $this->unpackDate($packed_time);
$str_time = date('Y-m-d H:i:s',$time); //TODO : to local time
private function unpackDate($data, $is_name=null)
{
$arr = unpack('N2', $data);
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
if (PHP_INT_SIZE == 4) {
$hi = $arr[1];
$lo = $arr[2];
$isNeg = $hi < 0;
// Check for a negative
if ($isNeg) {
$hi = ~$hi & (int)0xffffffff;
$lo = ~$lo & (int)0xffffffff;
if ($lo == (int)0xffffffff) {
$hi++;
$lo = 0;
} else {
$lo++;
}
}
// Force 32bit words in excess of 2G to pe positive - we deal wigh sign
// explicitly below
if ($hi & (int)0x80000000) {
$hi &= (int)0x7fffffff;
$hi += 0x80000000;
}
if ($lo & (int)0x80000000) {
$lo &= (int)0x7fffffff;
$lo += 0x80000000;
}
$value = $hi * 4294967296 + $lo;
if ($isNeg)
$value = 0 - $value;
} else {
// Upcast negatives in LSB bit
if ($arr[2] & 0x80000000)
$arr[2] = $arr[2] & 0xffffffff;
// Check for a negative
if ($arr[1] & 0x80000000) {
$arr[1] = $arr[1] & 0xffffffff;
$arr[1] = $arr[1] ^ 0xffffffff;
$arr[2] = $arr[2] ^ 0xffffffff;
$value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
} else {
$value = $arr[1]*4294967296 + $arr[2];
}
}
return $value / 1e3;
}
MORE DETAILS
Processing chain:
(1). insertion to Cassandra through .NET
(2). Cassandra data storage
(3). Pulling the data from PHP or .NET
Problem:
As for today, a date being 2014-04-15 10:00:00 in step (1), will come out as 2014-04-15 11:00:00 in step (3).
Details:
(regarding the date format in this chain)
(1). Local time in .NET (Timezone: "Europe/Paris"). Insertion cql that is being executed: "BEGIN BATCH USING CONSISTENCY ONE insert into my_table(id,'2014-04-11 8:00:00',...,'2014-04-15 10:00:00') values ('2036548',3.15,...,4.11) APPLY BATCH"
(2). ??? I don't know what Cassandra does here... ???
(3). Example of cql query to pull the data: "Select FIRST 100000 '2014-04-01 0:00:00'..'2014-04-16 0:00:00' from my_table where id=2036548". In php: date_default_timezone_set("Europe/Paris"); $str_time = date('Y-m-d H:i:s',$time);. In .NET: dateTime.ToLocalTime.
Extra info:
I think it worked well before the daylight saving time change some weeks ago. But I can not be sure about that.
If in step (1), if I changed the date to de date to UTC before inserting it, 2014-04-15 10:00:00 will become 2014-04-15 08:00:00 and the output will be 2014-04-15 09:00:00, which is still not correct.
I highly suspect that the trick here is between steps (1) and (2), that is to say, me not being able to understand how Cassandra treats dates.
Edit1:
#Ananth 's questions:
both cassandra and client run in the same datacenter?
It is complicated:
Insertion in .NET from server1, a different server from server-cassandra (datacenter).
PHP (to pull the data) running on server-cassandra.
.NET (to pull the data) running on server1, not on server-cassandra.
PHP and .NET pulling the same result.
Can you post your schema here?
Here it is
CREATE TABLE tsmeasures (
id int PRIMARY KEY
) WITH
comment='' AND
comparator=timestamp AND
read_repair_chance=0.100000 AND
gc_grace_seconds=0 AND
default_validation=double AND
min_compaction_threshold=4 AND
max_compaction_threshold=32 AND
replicate_on_write='true' AND
compaction_strategy_class='SizeTieredCompactionStrategy' AND
compression_parameters:sstable_compression='SnappyCompressor';
Edit2:
After testing it step by step, this is the result:
real date : 2014-04-15 17:00:00 (localtime)
cql text : '2014-04-15 15:00:00' (to UTC, done through .NET)
PHP Cassandra Unpack of this date => $ticks = 1397577600 (*) The unpack is done with the piece of code shown before
Ticks converted (through http://www.epochconverter.com/ )
GMT: Tue,
15 Apr 2014 16:00:00 GMT Your time zone: 4/15/2014 6:00:00 PM GMT+2
These results makes no sense to me...
More details:
cql insert:
"BEGIN BATCH USING CONSISTENCY ONE insert into tsmeasures(id,'2014-04-11 15:00:00',...,'2014-04-15 15:00:00') values ('2036548',0,...,4.85) APPLY BATCH"
cql fetch:
"SELECT '2014-04-10 16:00:00'..'2014-04-20 17:00:00' FROM tsmeasures WHERE id IN
(2036548,2036479,2036174,650877)"
Thus '2014-04-15 15:00:00' is included in the range of the fetch, and I can identify it because it is the highest value.
I will keep digging...
This seems to be a time zone issue. It appears you are neither specifying a timezone when storing nor when retrieving the timestamps. According to the documentation Cassandra applies the timezone of the coordinator node handling the write request if no timezone is supplied by the client. If timestamps shift between writing and reading them, that probably means all or some of your Cassandra nodes are not configured for the same timezone as your client is.
Before Edit
Is there a clock time sync problem between your client and cassandra? I would strictly recommend running NTP between your client and cassandra installation.
Post Edit
CREATE TABLE tsmeasures (
id int PRIMARY KEY
) WITH
comment='' AND
comparator=timestamp AND
read_repair_chance=0.100000 AND
gc_grace_seconds=0 AND
default_validation=double AND
min_compaction_threshold=4 AND
max_compaction_threshold=32 AND
replicate_on_write='true' AND
compaction_strategy_class='SizeTieredCompactionStrategy' AND
compression_parameters:sstable_compression='SnappyCompressor';
From what you have given , it looks like you are trying to get the insertion time .
Your problem might be due to clients running in different clock cycles with respect to cassandra. Cassandra just places a unix timestamp for each write.
So what is happening here from what i see.
You write from client using timestamp X(datastax driver sets this insertion timestamp). Cassandra writes with X.
You read with a timestamp Y. Cassandra tries to read with timestamp Y(So , as per your explanation, PHP client is there in a different location).
Both a are bound to differ.
Solution 1
Try to have a global NTP between the entire set up so that client clock cycles are in sync with cassandra.
Solution 2
Insert a column named timestamp which is user driven and do a range scan based on that
Solution 3
Set the insertion time in DML operations.

PHP Generate Unique Order Number with Date

I want to generate unique identificator in following 12 numeric format:
YYYYMMDDXXXX
Example:
201403052318
Where:
YYYYMMDD is a current date value and other XXXX is randomly generated value.
$today = date("Ymd");
$rand = sprintf("%04d", rand(0,9999));
$unique = $today . $rand;
Daily required unique volume is about 100. What methods using PHP should I use to prevent possible duplicates in rand values or make all id maximum unique? Maybe possible use current time functions to compact these numbers in last 4 characters?
EDITED:
Unique value connected to MySQL database as prime index of table. It is initial values not connected to any stored information in database.
You can't rely on rand() , There is a possibility you will generate a duplicate (Pretty rare for a rand(0,9999) to generate a duplicate, but that will at some point).
So instead of going for rand(), just create an incremental value (say.. starting from 1) and append to your generated date.
Next time when you regenerate a new id, grab that incremental value's (say if you had stored it somewhere.. must be 1 right ?) status, increment it and append it to your new date.
Not an ideal solution.. (Critics welcome)
You can make use of a uniqid coupled with sha-1 and time and do a substr() on them for first 4 chars.
<?php
$today = date("Ymd");
$rand = strtoupper(substr(uniqid(sha1(time())),0,4));
echo $unique = $today . $rand;
OUTPUT :
201403094B3F
I needed to do something similar, a solution that would keep time and also keep the id unique and i ended up with a solution to use PHP function time() like this
$reference_number = 'BFF-' . time(); you can change the BFF to something that makes more sense to your business logic.
My unique reference id looks like BFF-1393327176 and the number can be converted from Unix to real time which will give you, Tue, 25 Feb 2014 11:19:36
I hope this helps
If the unique values generated once, you just need to make conditional choice for the rand value and store the value in an array which is going to be the condition -using inarray-:
$amount = 100; // the amount of ids
$previousValues = array();
for ($i = 0; $i < $amount; $i++){
$rand = rand(0,9999);
while (in_array($rand, $previousValues)){
$rand = rand(0, 9999);
}
$previousValues[] = $rand;
$today = date("Ymd");
$unique = $today.$rand;
echo $unique."\n";
}
Checkout this demo.
A possible solution for creating unique "Unique Order Number" is following, I assume that you have orders table and field order_number, then the code is:
$orderNumber = DB::table('orders')->max('order_number') + random_int(10, 100);
If first order number is inserted as "100000000000" that method will give you this numbers:
100000000025
100000000056
100000000089
100000000123
100000000199
100000000232
100000000249
with that approach there is no possibility for non-unique number, but cons is that each number is greater the previous (not 100% random) but that approach is acceptable for most of the cases.

How to efficiently filter datetime column for extracting data?

I am usng sqlite to log data every 5 minutes to a column that is time stamped with and integer in Unix time. The user interface uses php code to extract data in various user selectable time frames which is then plotted using javascript. Charts typically have 12 data/time points and I need to extract data for plotting over different periods of say 1Hr/12Hr/24Hr/12days/month/year. So only need to extract 12 data rows per search. So for a 24Hr plot I need to only extract data at houly intervals (when minutes = 0) similarly for 12day plots at daily intervals (when mins=0 && hours=0) etc.
My php code for 1Hr works fine since the data is logged every 5min giving me 12 rows of data between search start time and end time. What is an efficient way of extracting data for the longer periods when number of rows between start time and end time is greater than 12? I need to further filter the search to efficiently extract only the data I need?
any suggestions - most appreciated - frank
$db = new MyDB(); // open database
$t=time(); // get current time
$q1 = "SELECT TimeStamp,myData FROM mdata WHERE ";
$q2 = " AND TimeStamp <=".$t; // end time
$q3 = " AND TimeStamp >=".($t-3600); // start time 1 hour earlier
$qer = $q1.$q2.$q3; // my search query form above parts
$result = $db->query($qer);
$json = array();
while ($data = $result->fetchArray(SQLITE_NUM)) {
$json[] = $data;
}
echo json_encode($json); // data is returned as json array
$db->close(); // close database connection
I think you should use WHERE date BETWEEN in your search query?
This kind of search could take up a lot of time once data builds up?
Since you already know the exact times you're interested in, you should probably just build an array of times and use SQL's IN operator:
$db = new MyDB(); // open database
$timeStep = 300; // Time step to use, 5 minutes here - this would be 3600 for hourly data
$t = time(); // get current time
$t -= $t % $timeStep; // round to the proper interval
$query = "SELECT TimeStamp,myData FROM mdata ";
$query .= "WHERE TimeStamp IN "
$query .= "(" . implode(",", range($t, $t + $timeStep * 12, $timeStep)) . ")";
$result = $db->query($query);
$json = array();
while ($data = $result->fetchArray(SQLITE_NUM)) {
$json[] = $data;
}
You'll need to do some different math for monthly data - try constructing 12 times with PHP's mktime() function.
Here are the references for the PHP implode() and range() functions I used.

Categories