Ignore seconds when querying created_at - php

I have a scheduled task that runs every 5 minutes that collects some stats on a server I run.
There is a small delay whilst it waits for the request to come back and so records are always being saved 2 or 3 seconds later. I.e the task runs at 2017-14-03 08:00:00, but the records are saved at 2017-14-03 08:00:03.
I am trying to pull the records out to display on a graph. The graph scales to the time period you want to look at (through hard coded buttons that refresh the graph with new data).
The first graph I am trying to do is one over the last 24 hours. Rather than bring back every 5 minute point for the last 24 hours, I just want one per hour. I have built a function to round down to the nearest hour and then get the last 24 hours based off that - it looks like this:
public function last24Hours()
{
$times = [];
$time = Carbon::now()->minute(0)->second(0);
$i = 1;
while($i <= 24)
{
array_push($times, $time->toDateTimeString());
$time->subHour();
$i++;
}
return $times;
}
Using the times returned, I am trying to query the model with whereIn() like so:
$stats = ServerTracking::whereIn('created_at', $this->last24Hours())->get();
The query runs, but nothing comes back - as the created_at time is a couple of seconds off from what I am querying.
I've hit a bit of a roadblock and cannot think of a way to get around this? Any ideas?

You can use selectRaw with a formatted date:
$stats = ServerTracking::selectRaw('foo,bar,DATE_FORMAT(created_at, "%Y-%m-%d %H:00:00") as hour_created')->get()->keyBy('hour_created');
All of the values in each hour will have the same hour_created, and keyBy will only keep one of them (from docs):
If multiple items have the same key, only the last one will appear in the new collection.
Just replace foo and bar with the other values you need. You'll either keep the 0:55 minute values, or the 0:00 minute values, depending on how you sort the query.
Come to think of it, you could use whereRaw to do it your way:
->whereRaw("DATE_FORMAT(created_at, '%Y-%m-%d %H:00:00') in (" .implode(",",$last24Hours). ")")

Not a solution per se, but I would take a different approach. Assuming I understood you are trying to query the last 24hours (1day), I would do
$now = Carbon::now();
$stats = ServerTracking::where('created_at', '<=', $now) //now
->where('created_at', '>=', $now->subHours(24)) //24hours ago
->get();
Using whereBetween is similar, but a bit shorter
$now = Carbon::now();
$stats = ServerTracking::whereBetween('created_at', [$now, $now->subHours(24)])
->get();

Related

How to get the result with these time intervals in php

I'm using a time clock system which, by default, records only the employee's entry and exit times. I'm customizing it so that it's possible to also record break times but I'm having trouble getting the break time to be subtracted from the total time.
This snippet of code is used to register the time between the check-in and check-out:
$time1 = Carbon::createFromFormat("Y-m-d H:i:s", $timeIN);
$time2 = Carbon::createFromFormat("Y-m-d H:i:s", $timeOUT);
$th = $time1->diffInHours($time2);
$tm = floor(($time1->diffInMinutes($time2) - (60 * $th)));
$totalhour = ($th.".".$tm);
The variable ($totalhour) receives the total value between the input register and the output register. It sends to the database in H.i format (hour.minutes), then another page searches for this information in the database and replaces the point (.) with (hr).
Based on this code, I did the same to get the interval start and end timestamps. I was able to get the time between the start time and end time interval with the code below:
$breakstart = table::attendance()->where([['idno', $idno]])->value('breakstart');
$breakend = table::attendance()->where([['idno', $idno]])->value('breakend');
$one = Carbon::createFromFormat("H:i:s", $breakstart);
$two = Carbon::createFromFormat("H:i:s", $breakend);
$breakone = $one->diffInHours($two);
$breaktwo = floor(($one->diffInMinutes($two) - (60 * $breakone)));
$totalbreak = $breakone.".".$breaktwo;
The $totalbreak variable stores the time taken between the start and end of the break. I was also successful in getting the time between this interval.
Now, I need the total time to be done by subtracting the time obtained from the record at the beginning of the interval to the record at the end of the interval.
I did with this code and got good result up to a point. Could you give me tips on how to get an assertive result in this case?
$totalhour = ($th.".".$tm) - ($totalbreak);
I tried to get the total time by subtracting the break time, but without success.

How to fetch data one line per each 15 minutes from the last 24 hour in Laravel 5.8?

I'm trying to get logs from the last 24 hours for a chart I'm building.
I'm using Laravel 5.8.
I need 1 line per every 15 minutes for the chart to be accurate.
The current state is one line per hour, I can't think of out to turn it into 15 minutes.
Please help me to make it work and make the code look as pretty as possible!
public function getDataDay(&$data) {
$data = $data->where('created_at', '>', Carbon::now()->subHours(23)->format('Y-m-d H:i:s'))
->select('id', 'part_id', 'data', 'created_at')
->selectRaw('HOUR(created_at) as hour')
->groupBy('hour')
->get();
}
use this, it is what i use in mysql
->selectRaw('FROM_UNIXTIME(FLOOR( UNIX_TIMESTAMP(created_at)/900 ) * 900) AS quaterhour')
->groupBy('quaterhour')
Of Course if you have mire than one day, you have to group also by years , month and days

How to get the duration of an inserted time by inserting another one with minute:seconds:milliseconds?

I am making a game mode in which I am trying to get the time a player has arrived at their destination after starting the mode and to do this I am using the insert of a date when it starts the mode it inserts a date and after reaching the your destination it registers another date and with both dates it calculates the time it took to get to the destination, with this I'm using date H:i:s (hours, minutes, seconds) but I need to take the time out and leave milliseconds after seconds example: i:s:u (minutes, seconds, milliseconds) but I'm not able to do this, I've tried it in several ways, basically everything works as follows:
1. I add in the player array a current date with hour, minutes, seconds;
$this->game[$player->getName()] = ["start" => strtotime('now')];
2. After the Player arrives at his destination he calculates the time of his trajectory creating another current date with already registered and using date and mktime to do the join and give a visual of time to the player;
$time = date('H:i:s', mktime(0, 0, str_replace("-", "", $this->game[$player->getName()]["start"] - strtotime('now'))));
3. Send the pretty message to the player about the time of his trajectory then time will be something like this: 01:45:23 (minute:seconds:milliseconds).
$player->sendMessage("You beat your time record by ".$time);
This is my method of doing, if you have another better method with the milli seconds added I accept the suggestion! Maybe there might be some errors in my code that I'm still not sure if they work correctly as the subtraction to calculate and join the current time with the previous one, tell me if it's right and if it is not correct correct me or do better. Thank you
Use microtime which returns the current Unix timestamp with microseconds
$game = [];
$game['start'] = microtime(true);
// Do stuff
sleep(3); // Without the sleep, start and end are the 'same'
$game['end'] = microtime(true);
$elapsedTime = ($game['end'] - $game['start']);
$minutes = floor($elapsedTime / 60);
$seconds = $elapsedTime % 60;
$milliseconds = number_format($elapsedTime - floor($elapsedTime),3);

How to check if time intervals are overlapping in Laravel 4.2/php?

So i have in a table tm_timekeep(id(pk), start(varchar), end(varchar)) [and a model for it] in a database with some time intervals in HH:MM format. For example:
id|start|end |
---------------
0 |10:00|10:30|
1 |11:23|11:55|
2 |13:15|15:39|
i would like to insert new rows and modify the existent ones if there are no overlappings between intervals.
if i would like to add as interval 11:57-12:40 would be ok, but 09:00-10:20 wouldn't because of 10:00-10:30, same for updateing a row. And if i would like to update a row, I need a function to check the condition before modifying the row. How should i do this?
My current code snippet:
public function checkInterval($start, $end){
$counter = 0;
$timekeepArray = Timekeep::all();
$start = date('H:i',Input::get('start'));
$end = date('H:i',Input::get('end'));
foreach($timekeepArray as $timekeep)
{
if($start <= $timekeep->end && $end>=$timekeep->start){
counter++; //in range
}
return counter;
}
}
After this i check the value of counter, but my problem is, that i always get 0 even if there are overlappings from input.
It's quite trivial - convert your time intervals to minutes, eg. 10:00 becomes 10 * 60 + 0 = 600 minutes, ends at 630 correspondingly.
Then, when you are trying to insert or update, and I would suggest you do it in Timekeep model, bound to 'saving' model event (see Model Events), you check whether:
1) Pick the last end time in minutes that is less than your new start time (that's a trivial SQL query)
2) See if there is any existing time in between that end time and your new end time - if there is, we have overlapping. Throw an exception, cancel model saving
There are several ways you could convert strings to minutes - you could store integers in MySQL (eg. 600) and then convert them to human readable hours either by defining getAttribute() or making your own methods. Or you could keep storing data as VARCHARs and do simple string manipulations (remove ':', multiply first part by 60) either in SQL or in PHP

Optimize feed fetching

I'm working on a site now that have to fetch users feeds. But how can I best optimize fetching if I have a database with, lets say, 300 feeds. I'm going to set up a cron-job to which fetches the feeds, but should I do it like 5 every second minute or something?
Any ideas on how to do this the best way in PHP?
If I understand you question, you are basically working on a feed agregator site?
You can do the following; start by refreshing every 1 hor (for example). When you have anough entries from some feed - calculate the average interval between entries. Then use that interval as an interval for fetching that feed.
For example, if the site published 7 articles in the last 7 days - you can fetch feeds from it every 24hours (1day).
I use this algorithm with a few changes, when I calculate this average interval I divide it by 2 (to be sure not to fetch too rarely). If the result is less than 60 minutes - I set the interval to 1h or it is bigger than 24 I set it to 24h.
For example, something like this:
public function updateRefreshInterval() {
$sql = 'select count(*) _count ' .
'from article ' .
'where created>adddate(now(), interval -7 day) and feed_id = ' . (int) $this->getId();
$array = Db::loadArray( $sql );
$count = $array[ '_count' ];
$interval = 7 * 24 * 60 * 60 / ( $count + 1 );
$interval = $interval / 2;
if( $interval < self::MIN_REFRESH_INTERVAL ) {
$interval = self::MIN_REFRESH_INTERVAL;
}
if( $interval > self::MAX_REFRESH_INTERVAL ) {
$interval = self::MAX_REFRESH_INTERVAL;
}
Db::execute( 'update feed set refresh_interval = ' . $interval . ' where id = ' . (int) $this->getId() );
}
The table is 'feed', 'refreshed' is the timestampt when the feed was last time refreshed and 'refresh_interval' is the desired time interval between two fetches of the same feed.
Based on the new information I think I would do something like this:
Let the "first" client initiate the updatework and store timestamp with it.
Everey other clients that will ask for the information get a cashed information until that information are to old. Next hit from a client will then refresh the cashe that then will be used by all clients till next time its to old.
The client that will actually initiate the updatework should not have to wait for it to finnish, just serv the old cashed version and continue to do it till the work is done.
That way you dont have to update anything if no clients are requesting it.
The best thing to do is to be 'nice' and not overload the feeds with lots of needless requests. I settled on a 1 hour update time for one of my webapps that monitors about 150 blogs for updates. I store the time they were last checked in the database and use that to decide when to update them. The feeds were added at random times so they aren't all updated at the same time.
I wrote pfetch to do this for me. It's small, but has a couple really important aspects:
It's written in twisted and can handle massive concurrency even when the network is slow.
It doesn't require any cron jockeying or anything.
I actually wrote it because my cron-based fetchers were becoming a problem. Now I have it configured to fetch some random stuff I want around the internet and then runs scripts whenever things change to update parts of my own web site.

Categories