从毫秒获取日期格式 m-d-Y H:i:s.u

Posted

技术标签:

【中文标题】从毫秒获取日期格式 m-d-Y H:i:s.u【英文标题】:Getting date format m-d-Y H:i:s.u from milliseconds 【发布时间】:2013-07-28 09:45:50 【问题描述】:

我正在尝试获取格式化的日期,包括以毫秒为单位指定的 UNIX 时间戳中的微秒。

唯一的问题是我不断得到 000000,例如

$milliseconds = 1375010774123;
$d = date("m-d-Y H:i:s.u", $milliseconds/1000);
print $d;

07-28-2013 11:26:14.000000

【问题讨论】:

奇怪的是问题要求转换毫秒,但每个人都回答如何转换微秒。我知道您可以在两者之间进行转换,但实际上回答问题而不是从 php 文档或其他地方复制和粘贴不相关的代码会很好。 【参考方案1】:
# PHP 8 type safe when using declare(strict_types=1);
echo date('m-d-Y H:i:s').substr((string) fmod(microtime(true), 1), 1, 4);

示例输出:

02-06-2019 16:45:03.53811192512512

如果您需要限制小数位数,那么下面的行 (credit mgutt) 将是一个不错的选择。 (使用下面的代码,6 将小数位数限制为 6。)

echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));

示例输出:

02-11-2019 15:33:03.624493

【讨论】:

您错过了几秒钟的精度和前导零。所以正确的版本应该是echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));。解释为什么我们需要09:***.com/a/28739819/318765 你又错过了精度;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7); 但请注意,substr() 不会舍入。与round() 结合使用,它会删除尾随零:***.com/questions/7493305/… 这就是我提出sprintf() 的原因。 @mgutt 第一个数字什么时候不是零?基本上,所需要的只是从 fmod 中获得 1 的余数时删除始终存在的零。问题要求微秒,但以秒的小数位形式表示。没有理由限制小数位数。更多的小数位只是更好的精度。 @mgutt 我在我的答案中添加了您的第一个建议替代方案,并解释说如果需要,这将是限制小数位数的好方法【参考方案2】:

php >= 7.3 的单行版本(用作函数参数):

printf("%s",


 (DateTime::createFromFormat('U.u', microtime(true)))
    ->setTimezone(new \DateTimeZone('UTC'))
    ->format("Y-m-d.H:i:s.v")

);

参见formats 中的vu

【讨论】:

看起来 PHP 7 不支持“v”。或者是吗?在我的测试中,.v 会失败,但 .u 不会。两者都在 PHP 8 中工作。【参考方案3】:

此功能适用于 php5.2 到 php7.4。这里包括测试代码:

#!/usr/bin/php
<?php

function dtfn ($t=null) // for filenames, date + time, year first, ms always 3 digits

  if (!$t) $t = microtime(true);
  $dtx = date('Y-m-d_H.i.s', $t);
  $ms = sprintf("%03u", 1000 * fmod($t,1));
  return "$dtx.$ms";


function xxx($t)

  echo sprintf("%12s: %s\n", $t, dtfn($t));


xxx(1);
xxx(1.0);
xxx(1.01);
xxx(1.0101);
xxx(1.23456789);

结果:

           1: 1970-01-01_01.00.01.000
           1: 1970-01-01_01.00.01.000
        1.01: 1970-01-01_01.00.01.010
      1.0101: 1970-01-01_01.00.01.010
  1.23456789: 1970-01-01_01.00.01.234

【讨论】:

【参考方案4】:

适用于 PHP 8.0+

最近修复了该错误,现在您可以使用带有小数部分的 UNIX 时间戳。

$milliseconds = 1375010774123;

$d = new DateTime( '@'. $milliseconds/1000 );
print $d->format("m-d-Y H:i:s.u");

输出:

07-28-2013 11:26:14.123000

对于 PHP

您需要先指定 UNIX 时间戳的格式,然后才能在 DateTime 对象中使用它。如其他答案所述,您可以使用createFromFormat()number_format() 来解决此错误

$milliseconds = 1375010774123;

$d = DateTime::createFromFormat('U.v', number_format($milliseconds/1000, 3, '.', ''));
print $d->format("m-d-Y H:i:s.u");

输出:

07-28-2013 11:26:14.123000

对于 PHP

如果您仍在使用早于 7.3 的 PHP,您可以将 U.v 替换为 U.u。它不会有任何区别,但毫秒格式标识符仅在 PHP 7.3 后才存在。

$milliseconds = 1375010774123;
//                                 V - Use microseconds instead of milliseconds
$d = DateTime::createFromFormat('U.u', number_format($milliseconds/1000, 3, '.', ''));
print $d->format("m-d-Y H:i:s.u");

输出:

07-28-2013 11:26:14.123000

【讨论】:

【参考方案5】:

基于@ArchCodeMonkey 的回答。

如果你有declare(strict_types=1),你必须将第二个参数转换为字符串

【讨论】:

【参考方案6】:

php.net 说:

微秒(在 PHP 5.2.2 中添加)。请注意,date() 将始终生成 000000,因为它需要一个整数参数,而如果 DateTime 是用微秒创建的,DateTime::format() 确实支持微秒。

所以使用简单:

$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>";

推荐并使用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 at point on "u"

注意u 是微秒(1 秒 = 1000000 µs)。

来自php.net的另一个例子:

$d2=new DateTime("2012-07-08 11:14:15.889342");

dateTime() 对php.net 的引用

我对作者的回答很简短。更多信息请查看作者:getting date format m-d-Y H:i:s.u from milliseconds

【讨论】:

我通常选择第二种形式,因为它更容易阅读和理解。此外,DateTime 比日期/时间函数更加灵活和健壮。处理微秒就是一个很好的例子。 @Geo 和 AlBundy 你是不是在 php 这不是很容易吗? date('m-d-Y H:i:s').(int)microtime(true); @Anant,确实很容易。但是错了。 ;) 你得到的只是几秒钟内的时代。 (很遗憾,microtime(false) 也无法使用。) 此代码无法在所有语言环境中正确运行。像德国这样的一些国家写“0,1234”或“0.1234”而不是“.1234”,因此您的代码为我提供以下输出:2012-07-08 11:14:15.0.889342【参考方案7】:

如果您使用的是 Carbon,您可以使用定义的规范“RFC3339_EXTENDED”。 或自定义它。

Carbon::RFC3339_EXTENDED = 'Y-m-d\TH:i:s.vP';

【讨论】:

【参考方案8】:

这是另一种我觉得更优雅/更简单的方法:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));

【讨论】:

【参考方案9】:

从 PHP 7.1 开始,您可以这样做:

$date = new DateTime( "NOW" );
echo $date->format( "m-d-Y H:i:s.u" );

它将显示为:

04-11-2018 10:54:01.321688

【讨论】:

【参考方案10】:

您可以使用输入格式 U.u 轻松完成此操作。

$now = DateTime::createFromFormat('U.u', microtime(true));
echo $now->format("m-d-Y H:i:s.u");

这会产生以下输出:

04-13-2015 05:56:22.082300

日期格式的 PHP 手册页:

U = 自 Unix 纪元以来的秒数 u = 微秒

http://php.net/manual/en/function.date.php


感谢 giggsey 指出我原始答案中的一个缺陷,将number_format() 添加到该行应该可以解决精确秒的情况。太糟糕了,感觉不再那么优雅了......

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));

http://php.net/manual/en/function.number-format.php


针对 DaVe 的时区说明。

如果未指定,通常createFromFormat() 方法将使用本地时区。

http://php.net/manual/en/datetime.createfromformat.php

但是,这里描述的技术是使用 microtime() 初始化 DateTime 对象,它返回自 Unix 纪元(格林威治标准时间 1970 年 1 月 1 日 00:00:00)以来经过的秒数。

http://php.net/manual/en/function.microtime.php

这意味着 DateTime 对象被隐式初始化为 UTC,这对于只想跟踪经过时间的服务器内部任务来说很好。

如果您需要显示特定时区的时间,则需要进行相应设置。但是,由于上述原因,这应该在初始化之后作为一个单独的步骤完成(使用createFromFormat() 的第三个参数)。

setTimeZone() 方法可用于完成此要求。

http://php.net/manual/en/datetime.settimezone.php

举个例子:

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
echo $now->format("m-d-Y H:i:s.u") . '<br>';

$local = $now->setTimeZone(new DateTimeZone('Australia/Canberra'));
echo $local->format("m-d-Y H:i:s.u") . '<br>';

产生以下输出:

10-29-2015 00:40:09.433818
10-29-2015 11:40:09.433818

注意如果要输入mysql,时间格式需要为:

format("Y-m-d H:i:s.u")

【讨论】:

注意:如果microtime(true) 恰好在第二秒运行,DateTime::createFromFormat('U.u', microtime(true)); 将返回 false。它返回“1438616239”而不是“1438616239.000000”。 感谢 giggsey,总是边缘案例让你受益匪浅! 很好的解决方案,谢谢。看来我正在失去本地时间,从微时间创建 $now 。有什么想法吗? @daVe 我已经添加了一些关于时区的信息,我希望这就是你所追求的。 number_format 始终是必需的,即使它不在精确的秒数上。否则,您将受制于precision PHP 配置选项(用于“显示”),从 PHP 7.0 开始,该选项默认不够高,导致精度损失(不精确到微秒)。【参考方案11】:

现在有了 PHP 7.0+,您可以执行以下操作:

$dateString = substr($millseconds_go_here,0,10);
$drawDate = new \DateTime(Date('Y-m-d H:i',$dateString));
$drawDate->setTimezone(new \DateTimeZone('UTC'));

这会按顺序执行以下操作:

    删除字符串的最后 4 个零,以便 Date() 可以处理日期。 使用日期将毫秒格式化为 DateTime 可以理解的日期时间字符串。 然后DateTime() 可以允许您修改您所在的时区,但请确保在使用DateTime() 函数和类之前设置date_default_timezone_set("Timezone");。 在您的类中使用构造函数以确保您在使用 DateTime() 类或函数时处于正确的时区是一种很好的做法。

【讨论】:

【参考方案12】:

我正在使用

echo date("Y-m-d H:i:s.").gettimeofday()["usec"];

output: 2017-09-05 17:04:57.555036

【讨论】:

【参考方案13】:

这是基于 ArchCodeMonkey 的回答。

但只是简化了,如果你只是想要一些快速有效的东西。

function DateTime_us_utc()
    return DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));

function DateTime_us()
    $now = DateTime_us_utc();
    return $now->setTimeZone(new DateTimeZone(date_default_timezone_get()));

那么对我来说

$now = DateTime_us();
$now->format("m-d-Y H:i:s.u");

【讨论】:

【参考方案14】:

如果您出于某种原因想要格式化像 javascript(new Date()).toISOString() 这样的日期,您可以在 PHP 中这样做:

$now = microtime(true);
gmdate('Y-m-d\TH:i:s', $now).sprintf('.%03dZ',round(($now-floor($now))*1000));

样本输出:

2016-04-27T18:25:56.696Z

只是为了证明减去整数并不会降低小数部分的准确性:

>>> number_format(123.01234567890123456789,25)
=> "123.0123456789012408307826263"
>>> number_format(123.01234567890123456789-123,25)
=> "0.0123456789012408307826263"

PHP 确实对小数位进行了四舍五入,但在两种情况下都以相同的方式四舍五入。

【讨论】:

没有。不要对浮点数使用数学,这是不准确的。也不要浪费时间调用几个函数。只需使用 substr() 将格式化日期截断为小数点后三位。 @LS 截断不会舍入小数点后第三位,这可能更不准确。在达到非常小的精度之前,浮点数不会崩溃; 3 位小数应该没问题。实际上,我认为我根本没有改变精度,浮点数越接近 0 就越准确。减去整数不应该改变小数位 AFAIK。 date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10)); 呢? @F8ER 如果你的$time 已经是毫秒,是的,这在技术上是可行的。不喜欢substr hack,但我想它适用于 2001 年到 2286 年之间的日期。 是的,$time 是 MS,但是 2286 呢,我的意思是为什么会这样想,怎么可能逃脱呢?【参考方案15】:
// Procedural
$fineStamp = date('Y-m-d\TH:i:s') . substr(microtime(), 1, 9);
echo $fineStamp . PHP_EOL;

// Object-oriented (if you must). Still relies on $fineStamp though :-\
$d = new DateTime($fineStamp);
echo $d->format('Y-m-d\TH:i:s.u') . PHP_EOL;

【讨论】:

【参考方案16】:

这是一个略短的方法。我没有创建高精度数字日期/时间,而是将微秒值转换为字符串,删除0,并将其添加到日期/时间字符串的末尾。我可以通过调整字符串长度参数轻松修剪小数位数;这里我使用4 来获取毫秒,但你可以使用7 来获取微秒。

$t = explode(" ",microtime());
echo date("m-d-y H:i:s",$t[1]).substr((string)$t[0],1,4);

对于 0.98236000 1407400573 的 microtime() 值,这将返回 08-07-14 01:08:13.982

【讨论】:

【参考方案17】:

文档说明如下:

微秒(在 PHP 5.2.2 中添加)。请注意 date() 将始终 生成 000000 因为它需要一个整数参数,而 DateTime::format() 确实支持微秒。

即,改用 DateTime。

【讨论】:

这不起作用! date_format(new DateTime(), 'u') 给出零:phpfiddle.org/lite/code/ggh-mvz 是的,根据上面的答案(和我的试验)new DateTime() 也将为你返回 0000。但是如果你在实例化它时提供一个微秒精度的时间,它就可以正常工作。 @scipilot 好的,那你是怎么做到的? @Geo 查看已接受的答案。 new DateTime( 'Y-m-d H:i:s.'.$micro);

以上是关于从毫秒获取日期格式 m-d-Y H:i:s.u的主要内容,如果未能解决你的问题,请参考以下文章

从 Presto SQL 中的字符串获取日期

js时间戳怎么转成日期格式

从 Android API 级别 19 上的 date.getTime() 获取毫秒数

java中怎么把Long转换成日期格式

如何从android中的毫秒获取日期

如何从日期对象python获取以毫秒(秒后3位小数)为单位的时间值?