A confusion about time() function in PHP - php

I cannot understand why the result of subtracting the current time from the variable of $_session['now'] that has included the previous time is zero.
I expected outputting the difference between the current time and the time when i have created the variable $student->now. Explain me please.
class Student
{
public function __set($key, $value)
{
$_SESSION[$key] = $value ;
}
public function __get($key)
{
return $_SESSION[$key];
}
}
session_start();
$student = new Student() ;
//__set function will be called ;
$student->now = time();
//__get function will be called ;
echo time() - $_SESSION["now"]; // output is zero ?!

The $_session['now'] variable is set in the line before the echo.
In the echo line the current time is compared to the time set in the line before.
Because both lines are executed directly after each other, both are executed within the same second. There will be a difference of milliseconds but time() function is measured in seconds, refer to: https://www.php.net/manual/en/function.time.php.
That's why both timestamps are the same and there is no difference between these when comparing them.

time() has a precision of ONE second, you are basically doing:
$now = time(); // e.g. 1627385278
echo time() - $now; // 1627385278 - 1627385278
This happens very fast, so the output is (almost always) zero.
The fact that your example code involves a "session" hints that you want to measure time between different HTTP requests. If that is the case, some logic is needed to ONLY set the stored value for the first time, but not thereafter.

Related

Given array of 1000 strings wih an associated time-interval value X for each, how do I perform a task for each of the strings, every x minutes?

I have a thousand (for example, could be more) strings and for each string, there is a field associated with it which represents time interval.
For each one of the strings, I need to perform a task which takes the string as input and produces some output, every X minutes (X being the time interval mentioned above).
If it was a single value of time interval for all the strings, then I would set up a single cron job and that would suffice; but I have a different value of time interval for each of the strings.
So I'll set up a thousand or more cron jobs. That does not feel right. So what would be the best way to solve this problem?
You might want to look into using a library that already did this instead of re-inventing the wheel yourself.
https://packagist.org/packages/peppeocchi/php-cron-scheduler
But, if you'd really want to code it yourself you'll need to have "two variables" one with last executed which has to be read from a file or database in between execution cycles, one with interval and have cron call your script every second/minute
Take a look at the proof of concept code here. Untested but it should point you in to how it should work in theory.
class Job
{
protected $interval = 0;
protected $lastrun = 0;
protected $job = null;
protected $filename = null;
public function __construct($id, $interval,callable $job)
{
$this->interval = $interval;
$this->job = $job;
$this->filename = __DIR__.'/'.$id.'.job';
$this->lastrun = file_get_contents($this->filename) ? : 0;
}
public function attemptRun($time)
{
if($time - $this->lastrun >= $this->interval) {
$this->run($time);
}
}
protected function run($time)
{
file_put_contents($this->filename, $time);
$this->job();
}
}
$jobs = [
new Job('addition', 10, function() { $a = 1; $b = 2; $c = $a + $b;}),
new Job('subtraction', 20, function() { $a = 1; $b = 2; $c = $a - $b;}),
];
var $currentTime = time();
foreach($jobs as $job) {
$job->attemptRun($currentTime);
}
Cron job: Run it every minute.
Let's say you have 3 strings in the format string_value-execute after certain minutes-
some_string-5
some_string_2-10
some_string_3-15
So, execution time if we start from 0 will have a series like this-
0
5 (execute first)
10 (execute first as well as second string)
15 (execute first and third string)
20 (execute first as well as second string)
25 (execute only first)
30 (execute first,second,third)
Database part:
Have 2 tables.
First table- has a single column having current cron minute.
second table- Have column as string , interval duration , next_execution_time
Now, insert into first table whenever you run it.
Secondly, do a "Select * from table_name where next_execution_time = current_got_fetched_from_first_table".
Introduce new strings- When you are doing so, insert as first start interval = current_cron_time + interval_duration to execute.
P.S- When processing completes, you also need to update the second table with their respective next_execution_time.

PHP Seconds to MM:SS Function

Currently I use the following javascript function to conver seconds to minutes and seconds.
function fmtMSS(s){return(s-(s%=60))/60+(9<s?':':':0')+s}
If I pass it 235 it returns 3:55
I've tried to convert it to php, but passing 235 to it I get 55
What have I done wrong ?
function fmtMSS($s){
return($s-($s%=60))/60+(9<$s?':':':0')+$s;
};
echo fmtMSS(235);
Thanks.
You have wrong logic part in your PHP version. Take a look at this:
function fmtMSS($s){
return(($s-($s%60))/60).(9<$s?':':':0').$s%60;
};
echo fmtMSS(235);
Sandbox: http://sandbox.onlinephpfunctions.com/code/163b767d435cf9db9058d03e95b873fb07e3fcbd
There is no reason to do it in a one-liner unless its the easiest and most readable way. Don't sacrifice readable code for shorter code.
The below function is the simplest and easiest way to convert seconds into a minute:seconds format. The reason for not using date("H:i", $s) (which would yield the same result) is that it will not scale well, and return incorrect results if $s ever gets high.
Divide by 60, floor it - that will get you the minutes. Multiply it by 60 and subtract it from $s, and you have your seconds.
function fmtMSS($s){
$minutes = floor($s/60);
$seconds = $s-$minutes*60;
return "$minutes:$seconds";
};
echo fmtMSS(235); // 3:55
Live demo
The reason your original code doesn't work, is because you're using + to join strings (as you would in JavaScript). However, in PHP, one uses . to contact two strings. The logic also seems to be a bit incorrect.
<?php
function fmtMSS($s){
$min = floor($s/60);
$sec = $s%60;
return $min.':'.$sec;
};
echo fmtMSS(235);
?>
Use this code- i have just edited your function.
for short:- echo gmdate("i:s", 235);

Using time() inside a while loop

For a school assignment we need to write a PHP script that counts for 1 second.
The following code I wrote should do exactly that was my thought:
$startTijd = time();
$teller = 0;
while($startTijd == time()){
echo 'Iteratie: ' . $teller . '<br>';
$teller++;
}
However, every time I run this or any PHP script similar to it that uses the time() function inside a while loop I get a 502 bad request from the server when I try to visit the page.
Your code as it is would not work (would not count one second exactly), because time() has a granularity of one second, and you have no guarantees that you landed on your page exactly at the tick of a second. So you need to synchronize.
To be clear, imagine calling time() several times, and let's suppose time() outputs in HH:MM:SS instead of Unix timestamps for legibility's sake:
Code
print time()
print time()
print time()
...
Output:
01:15:17
01:15:17
01:15:17
...
01:15:18
01:15:18
01:15:18
...
Your program probably currently does not work correctly because even in the little time that the loop runs, it generates a fantastic quantity of output (as can be seen above, time() remains "valid" for up to a whole second, and in that time a loop can execute lots of times). If there's some sort of resource limit on the PHP process, it's possible that this drives the process over its quota, resulting in the 502 error. You can check that by removing the echo from the loop, and just adding echo "Done." at the end.
You want to count between the instant in time in which time() transitions from 01:15:17 to 01:15:18, up to the instant when it again transitions to 01:15:19. Those instants will be separated by exactly one second.
What you would need to do is:
$startTijd = time()+1; // It is now maybe 01:15:17.93. We want to start
// counting at 01:15:18, so we need to wait for it.
while($startTijd !== time()) {
// Do nothing except maybe a very brief sleep to save CPU
usleep(5); // this is optional anyway.
}
// It is now 01:15:18.000003 and $startTijd is 01:15:18
$teller = 0;
// time() will remain equal to 01:15:18 for one second,
// while wall clock time increases from 01:15:18.000003 to 01:15:18.999999
while ($startTijd == time()) {
// Don't output anything here
$teller++;
}
// New transition detected.
// It is now e.g. 01:15:19.000137 and time() says 01:15:19.
echo 'Iteratie: ' . $teller . '<br>';
Alternately you can use microtime(true):
$teller = 0;
$endTijd = microtime(true) + 1.0;
while ($endTijd >= microtime(true)) {
// Don't output anything here
$teller++;
}
echo 'Iteratie: ' . $teller . '<br>';
Your code makes no sense... your while statment is only true if you computer is fast enough.
$startTijd = 100; # you set here the time represented by a number
while(100 == time() #101) { # here time is some milliseconds or seconds in the future
so after a second your while stops so that make not so much sense. Then use
while(true) {
and stop the while with a condition insight the while loop.

Comparing datetimes in php not working

I have the following session value
$_SESSION["time"] = 2015-01-09 23:57:38 (example value)
And the variable $test
$test = time() - (60 * 1); (1 minute)
$test = date("Y-m-d H:i:s",$test);
What I want to do is check whether 1 minute as passed. To do this I have the following code:
if(isset($_SESSION["time"]) && (strtotime($_SESSION["time"]) > $test)){
echo "first";
}else{
echo "second";
}
Independently to which logic comparison I use (< or >), after a minute a page refresh still echoes the same... any idea on why? I'm finding this really strange...
Comparision should be like
($_SESSION["time"] > $test)
PHP now will compare two string values instead of integer (return value from strtotime call) and string (return value from date call)
What he actually wants is...
strtotime($_SESSION["time"]) > strtotime($test))

Is there a set time out equivalent in php?

Is there a PHP equivalent to setting timeouts in JavaScript?
In JavaScript you can execute code after certain time has elapsed using the set time out function.
Would it be possible to do this in PHP?
PHP is single-threaded, and in general PHP is focused on the HTTP request cycle, so this would be tricky to allow a timeout to run code, potentially after the request is done.
I can suggest you look into Gearman as a solution to delegate work to other PHP processes.
You can use the sleep() function:
int sleep ( int $seconds )
// Delays the program execution for the given number of seconds.
Example:
public function sleep(){
sleep(1);
return 'slept for 1 second';
}
This is ugly, but basically works:
<?php
declare(ticks=1);
function setInterval($callback, $ms, $max = 0)
{
$last = microtime(true);
$seconds = $ms / 1000;
register_tick_function(function() use (&$last, $callback, $seconds, $max)
{
static $busy = false;
static $n = 0;
if ($busy) return;
$busy = true;
$now = microtime(true);
while ($now - $last > $seconds)
{
if ($max && $n == $max) break;
++$n;
$last += $seconds;
$callback();
}
$busy = false;
});
}
function setTimeout($callback, $ms)
{
setInterval($callback, $ms, 1);
}
// user code:
setInterval(function() {
echo microtime(true), "\n";
}, 100); // every 10th of a second
while (true) usleep(1);
The interval callback function will only be called after a tickable PHP statement. So if you try to call a function 10 times per second, but you call sleep(10), you'll get 100 executions of your tick function in a batch after the sleep has finished.
Note that there is an additional parameter to setInterval that limits the number of times it is called. setTimeout just calls setInterval with a limit of one.
It would be better if unregister_tick_function was called after it expired, but I'm not sure if that would even be possible unless there was a master tick function that monitored and unregistered them.
I didn't attempt to implement anything like that because this is not how PHP is designed to be used. It's likely that there's a much better way to do whatever it is you want to do.
Without knowing a use-case for your question it's hard to answer it:
If you want to send additional data to the client a bit later you can do a JS timeout on the client side with a handler that will make a new HTTP request to PHP.
If you want to schedule some task for a later time you can store that in a database and poll the DB in regular intervalls. It's not the best peforming solution but relatively easy to implement.
if ($currenturl != $urlto)
exit( wp_redirect( $urlto ) );
You can replace above two line with below code inside your function
if ($currenturl != $urlto)
header( "refresh:10;url=$urlto" );

Categories