毫秒时间戳是API开发过程中使用的一种时间格式,PHP语言通过microtime函数获取机器的时间戳;microtime函数底层依赖C语言的gettimeofday函数获取数据。毫秒时间戳是一个13位长度的整型数据。由于PHP语言特性,mictotime毫秒部分长度不固定,省略了0的部分,错误的使用会导致获取的毫秒时间戳长度异常。
#时间转换科普
1 2
| 1秒 = 1000毫秒 1毫秒 = 0.001秒
|
1 2
| 1秒 = 1000000微秒 1毫秒 = 1000微秒
|
#毫秒时间戳
1 2 3 4 5 6 7 8 9
| $time = explode(".", microtime(true));
$time[0] = $time[0] * 1000;
$microtime = $time[0] + substr($time[1], 0, 3);
echo intval($microtime);
|
由于microtime函数返回的毫秒部分是4位,gettimeofday函数返回的毫秒部分是6位;所以系统对时间精确度要求高的地方应该注意。
#microtime函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #ext/standard/microtime.c
PHP_FUNCTION(microtime) { _php_gettimeofday(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); }
static void _php_gettimeofday(INTERNAL_FUNCTION_PARAMETERS, int mode) { zend_bool get_as_float = 0; struct timeval tp = {0};
ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_BOOL(get_as_float) ZEND_PARSE_PARAMETERS_END();
if (gettimeofday(&tp, NULL)) { RETURN_FALSE; } if (get_as_float) { RETURN_DOUBLE((double)(tp.tv_sec + tp.tv_usec / MICRO_IN_SEC)); }
if (mode) { } else { RETURN_NEW_STR(zend_strpprintf(0, "%.8F %ld", tp.tv_usec / MICRO_IN_SEC, (long)tp.tv_sec)); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| # demo.c
#include<stdio.h> #include<stdlib.h> #include<sys/time.h> #include<unistd.h>
void microtime() { struct timeval tv; struct timezone tz;
gettimeofday(&tv, NULL);
double php_time; php_time = (double)(tv.tv_sec + tv.tv_usec / 1000000.00);
printf("tv_sec: %ld, tv_usec: %d, php_time: %f\n", tv.tv_sec, tv.tv_usec, php_time); }
int main() { for (int i = 0; i < 10000; i++) { microtime();
usleep(300); }
return 0; }
|
通过了解microtime函数的实现,其实可以发现PHP变量类型double会自动省略小数后面的0
1 2 3 4
| $a = (double) 1.2000;
var_dump($a);
|
#宏RETURN_DOUBLE
这里主要了解下PHP源码中函数返回值大都采用宏函数的形式返回,如RETURN_DOUBLE等,具体实现在zend_API.h和zend_types.h文件中。