php 带微秒的日期时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33691428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DateTime with microseconds
提问by Heru-Luin
In my code, I'm using DateTime
objects to manipulate dates, then convert them to timestamp in order to save them in some JSON files.
在我的代码中,我使用DateTime
对象来操作日期,然后将它们转换为时间戳,以便将它们保存在一些 JSON 文件中。
For some reasons, I want to have the same thing as DateTime (or something close), but with microseconds precision (that I would convert to float when inserting inside the JSON files).
出于某些原因,我想拥有与 DateTime 相同的东西(或接近的东西),但具有微秒精度(在插入 JSON 文件时我会转换为浮点数)。
My question is : is there a PHP objectthat is like DateTime
, but can handle microsecondstoo ?
我的问题是:是否有一个PHP对象就是喜欢DateTime
,但能处理微秒吗?
The goal is to be able to manipulate microtimes with objects.
目标是能够用对象操纵微时间。
In the date()documentation, there is something that indicates that DateTime can be created with microseconds, but I wasn't able to find how.
在date()文档中,有一些内容表明 DateTime 可以用微秒创建,但我无法找到方法。
u Microseconds (added in PHP 5.2.2). Note that date() will always generate 000000 since it takes an integer parameter, whereas DateTime::format() does support microseconds if DateTime was created with microseconds.
u 微秒(在 PHP 5.2.2 中添加)。请注意, date() 将始终生成 000000,因为它接受一个整数参数,而 DateTime::format() 确实支持微秒,如果 DateTime 是用微秒创建的。
I have tried to set the timestamp of a DateTime object with a floating value (microtime(true)
), but it doesn't work (I think it converts the timestamp to an int, causing the loss of the microseconds).
我试图用浮动值 ( microtime(true)
)设置 DateTime 对象的时间戳,但它不起作用(我认为它将时间戳转换为 int,导致微秒丢失)。
Here is how i tried
这是我尝试的方法
$dt = new DateTime();
$dt->setTimestamp(3.4); // I replaced 3.4 by microtime(true), this is just to give an example
var_dump($dt);
var_dump($dt->format('u'));
The .4
is not taken into account as you can see here (even though we can use the u
format, which corresponds to the microseconds).
在.4
不考虑,你可以在这里看到(尽管我们可以使用u
格式,对应于微秒)。
object(DateTime)[1]
public 'date' => string '1970-01-01 01:00:03' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Berlin' (length=13)
string '000000' (length=6)
EDIT : I saw this code, which allows to add microseconds to a DateTime, but I would need to apply a lot of modifications to the microtime before creating the DateTime. Since I will use this a lot, I want to do as little modifications to the microtime as possible before getting the "microtime object".
编辑:我看到了这段代码,它允许将微秒添加到 DateTime,但在创建 DateTime 之前,我需要对微时间应用大量修改。由于我会经常使用它,因此在获取“微时间对象”之前,我希望对微时间进行尽可能少的修改。
$d = new DateTime("15-07-2014 18:30:00.111111");
采纳答案by Heru-Luin
/!\ EDIT /!\
/!\ 编辑 /!\
I now use https://github.com/briannesbitt/Carbon, the rest of this answer is just here for historical reasons.
我现在使用https://github.com/briannesbitt/Carbon,这个答案的其余部分只是出于历史原因。
END EDIT
结束编辑
I decided to extend the class DateTime
using the tips you all gave me.
我决定DateTime
使用你们给我的技巧来扩展课程。
The constructor takes a float (from microtime
) or nothing (in this case it will be initialized with the current "micro-timestamp").
I also overrided 2 functions that were important : setTimestamp
and getTimestamp
.
构造函数接受一个浮点数(来自microtime
)或什么都没有(在这种情况下,它将用当前的“微时间戳”初始化)。我还覆盖了 2 个重要的函数:setTimestamp
和getTimestamp
.
Unfortunately, I couldn't solve the performances issue, although it's not as slow as I thought.
不幸的是,我无法解决性能问题,尽管它没有我想象的那么慢。
Here's the whole class :
这是整个班级:
<?php
class MicroDateTime extends DateTime
{
public $microseconds = 0;
public function __construct($time = 'now')
{
if ($time == 'now')
$time = microtime(true);
if (is_float($time + 0)) // "+ 0" implicitly converts $time to a numeric value
{
list($ts, $ms) = explode('.', $time);
parent::__construct(date('Y-m-d H:i:s.', $ts).$ms);
$this->microseconds = $time - (int)$time;
}
else
throw new Exception('Incorrect value for time "'.print_r($time, true).'"');
}
public function setTimestamp($timestamp)
{
parent::setTimestamp($timestamp);
$this->microseconds = $timestamp - (int)$timestamp;
}
public function getTimestamp()
{
return parent::getTimestamp() + $this->microseconds;
}
}
回答by MER
Here's a very simple method of creating a DateTime object that includes microtime.
这是创建包含微时间的 DateTime 对象的非常简单的方法。
I didn't delve into this question too deeply so if I missed something I apologize but hope you find this helpful.
我没有深入研究这个问题,所以如果我错过了什么,我深表歉意,但希望你觉得这有帮助。
$date = DateTime::createFromFormat('U.u', microtime(TRUE));
var_dump($date->format('Y-m-d H:i:s.u'));
I tested it out and tried various other ways to make this work that seemed logical but this was the sole method that worked. However there was a problem, it was returning the correct time portion but not the correct day portion (because of UTC time most likely) Here's what I did (still seems simpler IMHO):
我测试了它并尝试了各种其他方法来使这项工作看起来合乎逻辑,但这是唯一有效的方法。但是有一个问题,它返回了正确的时间部分而不是正确的日期部分(因为最有可能是 UTC 时间)这就是我所做的(恕我直言似乎仍然更简单):
$dateObj = DateTime::createFromFormat('U.u', microtime(TRUE));
$dateObj->setTimeZone(new DateTimeZone('America/Denver'));
var_dump($dateObj->format('Y-m-d H:i:s:u'));
Here's a working example: http://sandbox.onlinephpfunctions.com/code/66f20107d4adf87c90b5c8c914393d4edef180a2
这是一个工作示例:http: //sandbox.onlinephpfunctions.com/code/66f20107d4adf87c90b5c8c914393d4edef180a2
UPDATE
As pointed out in comments, as of PHP 7.1, the method recommended by Planplan appears to be superior to the one shown above.
更新
正如评论中所指出的,从 PHP 7.1 开始,Planplan 推荐的方法似乎优于上面显示的方法。
So, again for PHP 7.1 and later it may be better to use the below code instead of the above:
因此,对于 PHP 7.1 及更高版本,最好使用下面的代码而不是上面的代码:
$dateObj = DateTime::createFromFormat('0.u00 U', microtime());
$dateObj->setTimeZone(new DateTimeZone('America/Denver'));
var_dump($dateObj->format('Y-m-d H:i:s:u'));
Please be aware that the above works only for PHP versions 7.1 and above. Previous versions of PHP will return 0s in place of the microtime, therefore losing all microtime data.
请注意,以上仅适用于 PHP 7.1 及更高版本。以前版本的 PHP 将返回 0 代替微时间,因此会丢失所有微时间数据。
Here's an updated sandbox showing both: http://sandbox.onlinephpfunctions.com/code/a88522835fdad4ae928d023a44b721e392a3295e
这是一个显示两者的更新沙箱:http: //sandbox.onlinephpfunctions.com/code/a88522835fdad4ae928d023a44b721e392a3295e
NOTE: in testing the above sandbox I did not ever see the microtime(TRUE) failure which Planplan mentioned that he experienced. The updated method does, however, appear to record a higher level of precision as suggested by KristopherWindsor.
注意:在测试上述沙箱时,我没有看到 Planplan 提到他经历的 microtime(TRUE) 失败。然而,正如 KristopherWindsor 所建议的那样,更新后的方法似乎记录了更高水平的精度。
回答by Ben
Looking at a response on the PHP DateTime manual:
DateTime does not support split seconds (microseconds or milliseconds etc.)I don't know why this isn't documented. The class constructor will accept them without complaint, but they are discarded. There does not appear to be a way to take a string like "2012-07-08 11:14:15.638276" and store it in an objective form in a complete way.
So you cannot do date math on two strings such as:
DateTime 不支持分秒(微秒或毫秒等)我不知道为什么没有记录。类构造函数会毫无怨言地接受它们,但它们会被丢弃。似乎没有办法将像“2012-07-08 11:14:15.638276”这样的字符串完整地存储在客观形式中。
因此,您不能对两个字符串进行日期数学运算,例如:
<?php
$d1=new DateTime("2012-07-08 11:14:15.638276");
$d2=new DateTime("2012-07-08 11:14:15.889342");
$diff=$d2->diff($d1);
print_r( $diff ) ;
/* returns:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] => 0
)
*/
?>
You get back 0 when you actually want to get 0.251066 seconds.
当您真正想要获得 0.251066 秒时,您会返回 0。
However, taking a response from here:
但是,从这里得到回应:
$micro_date = microtime();
$date_array = explode(" ",$micro_date);
$date = date("Y-m-d H:i:s",$date_array[1]);
echo "Date: $date:" . $date_array[0]."<br>";
Recommended and use dateTime()
class from referenced:
推荐和使用dateTime()
类来自参考:
$t = microtime(true);
$micro = sprintf("%06d",($t - floor($t)) * 1000000);
$d = new DateTime( date('Y-m-d H:i:s.'.$micro, $t) );
print $d->format("Y-m-d H:i:s.u"); //note "u" is microseconds (1 seconds = 1000000 μs).
Reference of dateTime()
on php.net: http://php.net/manual/en/datetime.construct.php#
dateTime()
php.net 上的参考:http: //php.net/manual/en/datetime.construct.php#
回答by davejal
There are multiple options. But as already provided by Ben, I will try to give you another solution.
有多种选择。但是正如 Ben 已经提供的那样,我将尝试为您提供另一种解决方案。
If you provided more details on what kind of calculations you want to do it could be changed further.
如果您提供了有关您想要进行的计算类型的更多详细信息,则可以进一步更改。
$time =microtime(true);
$micro_time=sprintf("%06d",($time - floor($time)) * 1000000);
$date=new DateTime( date('Y-m-d H:i:s.'.$micro_time,$time) );
print "Date with microseconds :<br> ".$date->format("Y-m-d H:i:s.u");
or
或者
$time =microtime(true);
var_dump($time);
$micro_time=sprintf("%06d",($time - floor($time)) * 1000000);
$date=new DateTime( date('Y-m-d H:i:s.'.$micro_time,$time) );
print "Date with microseconds :<br> ".$date->format("Y-m-d H:i:s.u");
or
或者
list($ts,$ms) = explode(".",microtime(true));
$dt = new DateTime(date("Y-m-d H:i:s.",$ts).$ms);
echo $dt->format("Y-m-d H:i:s.u");
or
或者
list($usec, $sec) = explode(' ', microtime());
print date('Y-m-d H:i:s', $sec) . $usec;
回答by diskerror
This worked for me in PHP 7.2:
这在 PHP 7.2 中对我有用:
$dateTime = \DateTime::createFromFormat('U.u', sprintf('%f', $aFloat), $optionalTimezone);
I got to thinking that since the format code 'u'
would output only the microsecond part of a date when converting to a string then doing the reverse would be the same. And that it also expects a period character '.'
so if $aFloat
happened to be a whole number then default conversion to a string would leave off the decimal point. Initially I thought the float to string conversion needed '%.6f'
but the 'u'
is expecting a string which is left justified. Trailing zeros are unnecessary.
我开始想,因为格式代码'u'
在转换为字符串时只会输出日期的微秒部分,所以反过来做也是一样的。并且它还需要一个句点字符,'.'
所以如果$aFloat
碰巧是一个整数,那么默认转换为字符串将不带小数点。最初我认为需要将浮点数转换为字符串,'%.6f'
但'u'
希望得到一个左对齐的字符串。尾随零是不必要的。
回答by Valerii
/*
* More or less standard complete example. Tested.
*/
private static function utime($format, $utime = null, $timezone = null) {
if(!$utime) {
// microtime(true) had too fiew digits of microsecconds
$time_arr = explode( " ", microtime( false ) );
$utime = $time_arr[1] . substr( $time_arr[0], 1, 7 );
}
if(!$timezone) {
$timezone = date_default_timezone_get();
}
$date_time_zone = timezone_open( $timezone );
//date_create_from_format( "U.u", $utime ) - had a bug with 3-rd parameter
$date_time = date_create_from_format( "U.u", $utime );
date_timezone_set( $date_time, $date_time_zone );
$timestr = date_format( $date_time, $format );
return $timestr;
}
回答by B?a?ej Krzakala
since I resolved my issue i want to share it with You. Php71+ have microsecconds accuracy, if You want to convert it into nano accuracy just multiply it by 1000 (10^3).
自从我解决了我的问题,我想与您分享。Php71+ 具有微秒精度,如果您想将其转换为纳米精度,只需将其乘以 1000 (10^3)。
$nsTimestamp = (int) (new \DateTime())->getTimestamp() * 1000
回答by Onitech
$micro_seconds = microtime(false) * 1000000;
echo date('Y-m-d H:i:s.'. floor($micro_seconds));
more about date: https://www.php.net/manual/en/function.date.php
更多关于日期:https: //www.php.net/manual/en/function.date.php
more about microtime: https://www.php.net/manual/en/function.microtime.php
更多关于微时间:https://www.php.net/manual/en/function.microtime.php