time() is in seconds - is there one in milliseconds?
The short answer is:
$milliseconds = floor(microtime(true) * 1000);
Use microtime. This function returns a string separated by a space. The first part is the fractional part of seconds, the second part is the integral part. Pass in true to get as a number:
var_dump(microtime()); // string(21) "0.89115400 1283846202"
var_dump(microtime(true)); // float(1283846202.89)
Beware of precision loss if you use microtime(true).
There is also gettimeofday that returns the microseconds part as an integer.
var_dump(gettimeofday());
/*
array(4) {
["sec"]=>
int(1283846202)
["usec"]=>
int(891199)
["minuteswest"]=>
int(-60)
["dsttime"]=>
int(1)
}
*/
Short answer:
64 bits platforms only!
function milliseconds() {
$mt = explode(' ', microtime());
return intval( $mt[1] * 1E3 ) + intval( round( $mt[0] * 1E3 ) );
}
[ If you are running 64 bits PHP then the constant PHP_INT_SIZE equals to 8 ]
Long answer:
If you want an equilvalent function of time() in milliseconds first you have to consider that as time() returns the number of seconds elapsed since the "epoch time" (01/01/1970), the number of milliseconds since the "epoch time" is a big number and doesn't fit into a 32 bits integer.
The size of an integer in PHP can be 32 or 64 bits depending on platform.
From http://php.net/manual/en/language.types.integer.php
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18, except for Windows, which is always 32 bit. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.
If you have 64 bits integers then you may use the following function:
function milliseconds() {
$mt = explode(' ', microtime());
return intval( $mt[1] * 1E3 ) + intval( round( $mt[0] * 1E3 ) );
}
microtime() returns the number of seconds since the "epoch time" with precision up to microseconds with two numbers separated by space, like...
0.90441300 1409263371
The second number is the seconds (integer) while the first one is the decimal part.
The above function milliseconds() takes the integer part multiplied by 1000
1409263371000
then adds the decimal part multiplied by 1000 and rounded to 0 decimals
1409263371904
Note that both $mt[1] and the result of round are casted to int via intval(). This is necessary because they are floats and the operation on them without casting would result in the function returning a float with a loss in precision.
Finally, that function is slightly more precise than
round(microtime(true)*1000);
that with a ratio of 1:10 (approx.) returns 1 more millisecond than the correct result.
This is due to the limited precision of the float type (microtime(true) returns a float).
Anyway if you still prefer the shorter round(microtime(true)*1000); I would suggest casting to int the result.
Even if it's beyond the scope of the question it's worth mentioning that if your platform supports 64 bits integers then you can also get the current time in microseconds without incurring in overflow.
If fact 2^63 - 1 (biggest signed integer) divided by 10^6 * 3600 * 24 * 365 (approximately the microseconds in one year) gives 292471.
That's the same value you get with
echo intdiv( PHP_INT_MAX, 1E6 * 3600 * 24 * 365 );
In other words, a signed 64 bits integer have room to store a timespan of over 200,000 years measured in microseconds.
You may have then
function microseconds() {
$mt = explode(' ', microtime());
return intval( $mt[1] * 1E6 ) + intval( round( $mt[0] * 1E6 ) );
}
As other have stated, you can use microtime() to get millisecond precision on timestamps.
From your comments, you seem to want it as a high-precision UNIX Timestamp. Something like DateTime.Now.Ticks in the .NET world.
You may use the following function to do so:
function millitime() {
$microtime = microtime();
$comps = explode(' ', $microtime);
// Note: Using a string here to prevent loss of precision
// in case of "overflow" (PHP converts it to a double)
return sprintf('%d%03d', $comps[1], $comps[0] * 1000);
}
Shortest version of string variant (32-bit compatibile):
$milliseconds = date_create()->format('Uv');
echo date('Y-m-d H:i:s.') . gettimeofday()['usec'];
output:
2016-11-19 15:12:34.346351
Use microtime(true) in PHP 5, or the following modification in PHP 4:
array_sum(explode(' ', microtime()));
A portable way to write that code would be:
function getMicrotime()
{
if (version_compare(PHP_VERSION, '5.0.0', '<'))
{
return array_sum(explode(' ', microtime()));
}
return microtime(true);
}
This works even if you are on 32-bit PHP:
list($msec, $sec) = explode(' ', microtime());
$time_milli = $sec.substr($msec, 2, 3); // '1491536422147'
$time_micro = $sec.substr($msec, 2, 6); // '1491536422147300'
Note this doesn't give you integers, but strings. However this works fine in many cases, for example when building URLs for REST requests.
If you need integers, 64-bit PHP is mandatory.
Then you can reuse the above code and cast to (int):
list($msec, $sec) = explode(' ', microtime());
// these parentheses are mandatory otherwise the precedence is wrong!
// ↓ ↓
$time_milli = (int) ($sec.substr($msec, 2, 3)); // 1491536422147
$time_micro = (int) ($sec.substr($msec, 2, 6)); // 1491536422147300
Or you can use the good ol' one-liners:
$time_milli = (int) round(microtime(true) * 1000); // 1491536422147
$time_micro = (int) round(microtime(true) * 1000000); // 1491536422147300
try this:
public function getTimeToMicroseconds() {
$t = microtime(true);
$micro = sprintf("%06d", ($t - floor($t)) * 1000000);
$d = new DateTime(date('Y-m-d H:i:s.' . $micro, $t));
return $d->format("Y-m-d H:i:s.u");
}
PHP 5.2.2 <
$d = new DateTime();
echo $d->format("Y-m-d H:i:s.u"); // u : Microseconds
PHP 7.0.0 < 7.1
$d = new DateTime();
echo $d->format("Y-m-d H:i:s.v"); // v : Milliseconds
$timeparts = explode(" ",microtime());
$currenttime = bcadd(($timeparts[0]*1000),bcmul($timeparts[1],1000));
echo $currenttime;
NOTE: PHP5 is required for this function due to the improvements with
microtime() and the bc math module is also required (as we’re dealing
with large numbers, you can check if you have the module in phpinfo).
Hope this help you.
$the_date_time = new DateTime($date_string);
$the_date_time_in_ms = ($the_date_time->format('U') * 1000) +
($the_date_time->format('u') / 1000);
This is my implementation, should work on 32bit as well.
function mstime(){
$mstime = explode(' ',microtime());
return $mstime[1].''.(int)($mstime[0]*1000);
}
If you want to see real microseconds, you will need to change the precision setting in php.ini to 16.
After that, microsecond(true) gave me the output of 1631882476.298437.
So I thought that I need to divide the remainder (298437) with 1000, but in fact, the remainder is 0.298437 of a second. So I need to multiply that by 1000 to get the correct result.
function get_milliseconds()
{
$timestamp = microtime(true);
return (int)(($timestamp - (int)$timestamp) * 1000);
}
I personaly use this:
public static function formatMicrotimestamp(DateTimeInterface $dateTime): int
{
return (int) substr($dateTime->format('Uu'), 0, 13);
}
Use this:
function get_millis(){
list($usec, $sec) = explode(' ', microtime());
return (int) ((int) $sec * 1000 + ((float) $usec * 1000));
}
Bye
Related
To use modular exponentiation as you would require when using the Fermat Primality Test with large numbers (100,000+), it calls for some very large calculations.
When I multiply two large numbers (eg: 62574 and 62574) PHP seems to cast the result to a float. Getting the modulus value of that returns strange values.
$x = 62574 * 62574;
var_dump($x); // float(3915505476) ... correct
var_dump($x % 104659); // int(-72945) ... wtf.
Is there any way to make PHP perform these calculations properly? Alternatively, is there another method for finding modulus values that would work for large numbers?
For some reason, there are two standard libraries in PHP handling the arbitrary length/precision numbers: BC Math and GMP. I personally prefer GMP, as it's fresher and has richer API.
Based on GMP I've implemented Decimal2 class for storing and processing currency amounts (like USD 100.25). A lot of mod calculations there w/o any problems. Tested with very large numbers.
use this
$num1 = "123456789012345678901234567890";
$num2 = "9876543210";
$r = mysql_query("Select #sum:=$num1 + $num2");
$sumR = mysql_fetch_row($r);
$sum = $sumR[0];
have you taken a look at bcmod()? php has issues with integers over 2^31 - 1 on 32 bit platforms.
var_dump(bcmod("$x", '104659') ); // string(4) "2968"
I suggest you try BigInteger. If that doesn't work out, you may use SWIG to add C/C++ code for the big integer calculations and link it into your code.
I wrote a very small code for you that will surely work in case of big numbers-
<?php
$x = gmp_strval(gmp_mul("62574","62574")); // $x="3915505476"
$mod=gmp_strval(gmp_mod($x,"104659")); //$mod="2968"
echo "x : ".$x."<br>";
echo "mod : ".$mod;
/* Output:
x : 3915505476
mod : 2968
*/
?>
You simply have to use strings for storing big numbers and to operate on them use GMP functions in PHP.
You may check some good GMP functions in the official PHP manual here-
http://php.net/manual/en/ref.gmp.php
I found another solution, but the number will be stored as a string. As soon as you cast it back to a numeric, you'll be restricted to the precision of the underlying platform. On a 32 bit platform, the largest int you can represent as an int type is 2,147,483,647:
/**
* #param string $a
* #param string $b
* #return string
*/
function terminal_add($a,$b)
{
exec('echo "'.$a.'+'.$b.'"|bc',$result);
$ret = "";
foreach($result as $line) $ret .= str_replace("\\","",$line);
return $ret;
}
// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"
$x = 62574 * 62574;
// Cast to an integer
$asInt = intval($x);
var_dump($asInt);
var_dump($asInt % 104659);
// Use use sprintf to convert to integer (%d), which will casts to string
$asIntStr = sprintf('%d', $x);
var_dump($asIntStr);
var_dump($asIntStr % 104659);
<?php
function add($int1,$int2){
$int1 = str_pad($int1, strlen($int2), '0', STR_PAD_LEFT);
$int2 = str_pad($int2, strlen($int1), '0', STR_PAD_LEFT);
$carry = 0;
$str = "";
for($i=strlen($int1);$i>0;$i--){
$var = $int1[$i-1] + $int2[$i-1] + $carry;
$var = str_pad($var, 2, '0', STR_PAD_LEFT);
$var = (string) $var;
$carry = $var[0];
$str = $str . $var[1];
}
$res = strrev($str.$carry);
echo ltrim($res,"0");
}
add($int1,$int2);
?>
I'm running a benchmark test of doing nothing so the results is pretty fast.
Here is my code:
$time_start = microtime(true);
//Do Nothing...
$time = microtime(true) - $time_start;
echo 'Took '.$time.' seconds<br>';
The problem is when I try to echo the results I'm getting this:
Took 1.3828277587891E-5 seconds
I'm expecting to get a regular decimal number like:
Took 0.000000008231 seconds
Is it possible to force php to display it as regular decimal number ?
If you want your big numbers, then try this:
//$i = gmp_init( $time ); // i think you need that only if you want convert a string to an int/flaot
echo gmp_strval( $time );
gmp_strval PHP > 4.0.4 / PHP 5.
Mor infos http://php.net/manual/en/function.gmp-strval.php
You can use the printf or sprintf function. Here's a sample from http://php.net/manual/en/function.sprintf.php
<?php
$n = 43951789;
$u = -43951789;
$c = 65; // ASCII 65 is 'A'
// notice the double %%, this prints a literal '%' character
printf("%%b = '%b'\n", $n); // binary representation
printf("%%c = '%c'\n", $c); // print the ascii character, same as chr() function
printf("%%d = '%d'\n", $n); // standard integer representation
printf("%%e = '%e'\n", $n); // scientific notation
printf("%%u = '%u'\n", $n); // unsigned integer representation of a positive integer
printf("%%u = '%u'\n", $u); // unsigned integer representation of a negative integer
printf("%%f = '%f'\n", $n); // floating point representation
printf("%%o = '%o'\n", $n); // octal representation
printf("%%s = '%s'\n", $n); // string representation
printf("%%x = '%x'\n", $n); // hexadecimal representation (lower-case)
printf("%%X = '%X'\n", $n); // hexadecimal representation (upper-case)
printf("%%+d = '%+d'\n", $n); // sign specifier on a positive integer
printf("%%+d = '%+d'\n", $u); // sign specifier on a negative integer
for your example, you can use -for instance- :
<?php
$time_start = microtime(true);
//Do Nothing...
$time = microtime(true) - $time_start;
echo 'Took '.sprintf("%f",$time).' seconds<br>';
You can even change the precision this way:
sprintf("%.1f",$time) // -> 0.0 seconds
sprintf("%.10f",$time) // -> 0.0000059605 seconds
you can use number_format()
Check http://php.net/number_format
I know the formular for conversion from Degree to Milliseconds and vice-versa. It can be implemented like that:
protected function decimal_to_milisecond($dec) {
if (!empty($dec)) {
$vars = explode(".",$dec);
if (count($vars) == 2) {
$deg = $vars[0];
$tempma = "0.".$vars[1];
$tempma = $tempma * 3600;
$min = floor($tempma / 60);
$sec = $tempma - ($min*60);
return round((((($deg * 60) + $min) * 60 + $sec) * 1000));
}
else return false;
} else return false;
}
function milisecond_to_decimal($sec) {
if (!empty($sec)) {
$s = $sec / 1000;
$d = (int)($s / 3600);
$s = $s % 3600;
$m = (int)($s / 60);
$s %= 60;
$ret = substr($d+((($m*60)+($s))/3600),0);
} else return null;
return $ret;
}
Scenario: I convert from Degree to Miliseconds and continue converting from Miliseconds to Degree. The converted value has some difference with original value. I want the value is exact as the orginal value as well. For example:
$lat = "1284146";
$long = "503136198";
$lat1 = milisecond_to_decimal($lat);
$long1 = milisecond_to_decimal($long);
$result1 = decimal_to_milisecond($lat1);
$result2 = decimal_to_milisecond($long1);
var_dump($result1, $result2);
The output is float(1284000) and float(503136000)
Is there another way to reduce difference is caused by conversion between degree and milliseconds?
There are 360 degrees (longitude), 60 minutes per degree, 60 secondes per minute, 1000 milliseconds per second. So at most
360*60*60*1000 milliseconds = 1 296 000 000 milliseconds
That fits well on 31 bits, so the idea would be to first convert to an integer, and perform as much operations as possible in integer.
Note that if you use single precision floating point, you'll get a 24 bits significand and will loose accuracy under 1 tenth of second (log2(360*60*60*10) is about 23.6).
I would recommend to store results in double precision (53 bits significand).
EDIT
What I was suggesting is to perform the conversion all at once, if there is a way to use double precision for representing $decimaldegrees (I don't know php enough to tell so), something like:
$millis = (int)( round( $decimaldegrees * (60*60*1000) ) );
Then if ever you want to decompose into DMS (but these variables are not used in your code):
$ms = $millis % 1000;
$sec = ($millis / 1000) % 60;
$min = ($millis / (60*1000)) % 60;
$deg = ($millis / (60*60*1000)) % 360;
Ater a deeper look at you code, it seems you are separating the decimal part first $tempma = "0.".$vars[1];
That could work if you work on the decimal representation string, because in this case that fits well even on a single precision float (log2(60*60*1000) is about 21.8). So the beginning could be replaced with:
$deg = (int) $vars[0];
$frac = "0.".$vars[1];
$millis = (int)( round( $frac * (60*60*1000) ) );
$millis = deg + millis;
From the example of output you gave, it sounds like the problem comes from the other conversion milisecond_to_decimal, presumably because some arithmetic operation is performed with integer arithmetic and thus discards the milliseconds.
Once again, I don't know php enough, but wouldn't $s = $s % 3600; in fact operate on (int)(%s) and thus discard the milliseconds?
You would need to find something equivalent to C function fmod or modf.
Once again, you could do all operation at once if there is a way to do it in double precision:
$decimaldegrees = ((double)($millis)) / (60*60*1000);
If you don't have access to double precision, you can't recompose safely, single precision does not have enough bits...
You would need to operate on separate string parts, caring of leading zeros in fraction part
Anyway, I strongly suggest to perform unit tests, that is to test your two functions separately, this way you'll get a better understanding of what works and what not.
In languages like C or Python 2, if I divide an integer by an integer, I get an integer:
>>> 8/3
2
But in PHP, if I divide an integer by another integer with /, sometimes I get a float:
php > var_dump(6/3);
int(2)
php > var_dump(8/3);
float(2.6666666666667)
I'd like to do division like in Python or C, so that 8/3 is 2. How can I do that in PHP?
As of PHP 7, we can use the intdiv built-in function to get an integer value:
intdiv(8,3); // 2
For earlier versions of PHP, we can use the round() function to get an integer rounded value:
round(8 / 3); // 3
Or we can use the floor() function to get an integer value:
floor(8 / 3); // 2
In PHP 7, there is intdiv function doing exactly what you want.
Usage:
intdiv(8, 3);
Returns 2.
There is no integer division operator in PHP. 1/2 yields the float 0.5. The value can be casted to an integer to round it downwards, or the round() function provides finer control over rounding.
var_dump(25/7); // float(3.5714285714286)
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7)); // float(4)
PhP manual
use this....
intval(1700000 / 300000 )...
this returns the integer value.
FOR PHP 7 try intdiv() Function:
Syntax: int intdiv($dividend, $divisor)
<?php
$dividend = 19;
$divisor = 3;
echo intdiv($dividend, $divisor);
?>
For Older versions of PHP:
<?php
// Convert $total_minutes to hours and minutes.
$total_minutes = 640;
$minutes = $total_minutes % 60;
$hours = ($total_minutes - $minutes) / 60;
echo "Time taken was $hours hours $minutes minutes";
?>
You can use the shortform by adding |0 to the end
8/3|0
There are several ways to perform integer division in PHP. The language doesn't have an operator for integer division, but there are several options for rounding the floating point quotient to an integer:
<?php
$pos = 1;
$neg = -1;
$divisor = 2;
// No rounding (float division)
var_dump($pos / $divisor); // 0.5 (float)
var_dump($neg / $divisor); // -0.5 (float)
// Round toward zero (like C integer division)
var_dump((int)($pos / $divisor)); // 0 (int)
var_dump((int)($neg / $divisor)); // 0 (int)
// Round half away from zero
var_dump(round($pos / $divisor)); // 1 (float)
var_dump(round($neg / $divisor)); // -1 (float)
// Round down
var_dump(floor($pos / $divisor)); // 0 (float)
var_dump(floor($neg / $divisor)); // -1 (float)
# And on PHP 7 you can round toward zero with intdiv():
var_dump(intdiv($pos, $divisor)); // 0 (int)
var_dump(intdiv($neg, $divisor)); // 0 (int) Rounded toward zero
On PHP 7 you can use intdiv($p, $q) to directly perform integer division. This is equivalent to (int)($p / $q) on PHP 5.
(int)(1700000 / 300000);
use type casting.
For PHP version 7 => intdiv(a,b)
And for versions less than 7 (like 5.6) => (int)floor(abs(a/b))
I'm having a terrible time convincing myself what I've done here is a good idea. The specific section I find objectionable is:
return ((float)($now+$sec).'.'.$mic);
In order to preserve the floating point precision, I'm forced to either fall back on the BC or GMP libraries (neither of which is always available). In this case, I've resorted to jamming the numbers together with string concatenation.
<?php
// return the current time, with microseconds
function tick() {
list($sec, $mic, $now) = sscanf(microtime(), "%d.%d %d");
return ((float)($now+$sec).'.'.$mic);
}
// compare the two given times and return the difference
function elapsed($start, $end) {
$diff = $end-$start;
// the difference was negligible
if($diff < 0.0001)
return 0.0;
return $diff;
}
// get our start time
$start = tick();
// sleep for 2 seconds (should be ever slightly more than '2' when measured)
sleep(2);
// get our end time
$end = tick();
$elapsed = elapsed($start, $end);
// should produce output similar to: float(2.00113797188)
var_dump($elapsed);
?>
If I attempt to add two numbers like 123456789 (representing a timestamp) and 0.0987654321 (representing microseconds), using the addition operator (+) I invariably end up with 123456789.099. Even when casting the integer to float, the result is the same.
Is there a solution for this issue which is 1) not a hack and 2) doesn't involve string concatenation? I shouldn't have to fall back on this sort of garbled code in order to get an accurate timestamp with microsecond resolution.
Edit: As S. Gehrig has explained, floating point numbers in PHP can be, at times, a bit tricky to display. The "precision" indicated in the PHP configuration is regarding display. The actual values are not rounded like I thought. A far simpler solution to the above code would look like so:
// return the current time, with microseconds
function tick() {
return microtime(true);
}
// compare the two given times and return the difference
function elapsed($start, $end) {
return $end-$start;
}
// get our start time
$start = tick();
// sleep for 2 seconds (should be ever slightly more than '2' when measured)
sleep(2);
// get our end time
$end = tick();
$elapsed = elapsed($start, $end);
// should produce output similar to: float(2.00113797188)
var_dump($elapsed);
If you were to examine $start or $end before subtracting one from the other, it might appear they were rounded to the hundredths position. This is not the case. It seems arbitrary precision is maintained for arithmetic while the display is limited.
Why don't you use microtime(true) which simply returns a microsecond timestamp as float? The parameter [bool] $get_as_float was added in PHP 5.0.0.
Regarding the comment about the "loss" of precision:
$start = microtime(true);
$end = microtime(true);
echo $end - $start;
// prints 7.1526861190796
microtime(true) is not limited to 2 decimal places. What the poster encounters is the effect of the configuration setting precision which controls how many decimal places will be printed when outputting float variables. This has nothing to do with the internal precision microtime(true) uses. You can always use number_format() or (s)printf() to format the output to the precision you like.
First, spligak, I see that your code contains an error.
list($sec, $mic, $now) = sscanf(microtime(), "%d.%d %d");
return ((float)($now+$sec).'.'.$mic);
If $mic has fewer than six digits, you get garbage results. Do a desk check on
the case where microtime() returns "0.000009 1234567890"
Second, you can greatly reduce the floating-point error as follows:
(WARNING: untested code!)
// compare the two given times and return the difference
// get our start time
$start = microtime();
// sleep for 2 seconds (should be ever slightly more than '2' when measured)
sleep(2);
// get our end time
$end = microtime();
// work around limited precision math
// subtract whole numbers from whole numbers and fractions from fractions
list($start_usec, $start_sec) = explode(" ", $start);
list($end_usec, $end_sec) = explode(" ", $end);
$elapsed = ((float)$end_usec)-((float)$start_usec);
$elapsed += ((float)$end_sec)-((float)$start_sec);
// please check the output
var_dump($elapsed);
Floating point types are inherently imprecise. Either live with it, or don't use them.