负时间戳的DateTime(以微秒为单位)(<1970)

时间:2018-12-12 17:41:37

标签: php datetime

如何以微秒为单位从Unix时间戳正确实例化DateTime?

php > echo (DateTime::createFromFormat('U.u', '-128649660.000000'))->format('Y-m-d H:i:s.u U.u');
1965-12-03 23:59:00.000000 -128649660.000000
php > echo (DateTime::createFromFormat('U.u', '-128649659.999998'))->format('Y-m-d H:i:s.u U.u');
1965-12-03 23:59:01.999998 -128649659.999998

如您所见,时间戳中的2us差异总计为2s-2us的差异。
我相信正确的结果是1965-12-03 23:59:00.000002

如何在没有手动重新计算负时间戳的情况下实现便捷的方式?


也许我应该始终将“ U.u”格式解释为“ U + 0.u”值吗?
我的意思是u不是微秒部分,而是与整数部分有正差?

3 个答案:

答案 0 :(得分:2)

一种方法是,假设时间戳记为负,则强制进行微秒的计算:

$date = DateTime::createFromFormat('U', '-128649659');
$ms = (1000000-999998);
echo $date->modify("-1 second +$ms microsecond")->format('Y-m-d H:i:s.u U.u');
1965-12-03 23:59:00.000002 -128649660.000002

因此,基本上,起初您忽略了微秒部分。稍后,您只需要计算微秒部分。

如果做笔记,U.u部分将是错误的,因此在这种情况下没有用。

不确定是否适用于每种情况,我们将不胜感激任何建议。

答案 1 :(得分:1)

您可以使用类似的方法将时间字符串转换为正确的格式。

function convertNegativeTimestamp(string $ts) {
    $parts = explode('.', $ts);
    if( count($parts) != 2 ) {
        return $ts;
    }
    $parts[0] = intval($parts[0]);
    if( $parts[0] < 0 ) {
        $parts[1] = intval(str_pad($parts[1], 6, '0'));
        $parts[1] = 1000000 - $parts[1];
        return sprintf('%d.%06d', $parts[0], $parts[1]);
    } else {
        return $ts;
    }
}

答案 2 :(得分:0)

好,那么我的解决方法是:

function uDate($ts) {
  $dts = floor($ts);                             // integer part
  $uts = number_format($ts - $dts, 6, '.', '');  // fraction part                    
  return DateTime::createFromFormat('U\+0.u', "$dts+$uts");
}
function uTime(\DateTimeInteface $dt) { // Reverse action
  $dts = $dt->format('U');
  $uts = $dt->format('0.u');
  return number_format($dts+$uts, 6, '.', '');
}

echo uDate('-128649659.999998')->format('Y-m-d H:i:s.u'), PHP_EOL; // 1965-12-03 23:59:00.000002
echo uDate('-128649660.000002')->format('Y-m-d H:i:s.u'), PHP_EOL; // 1965-12-03 23:58:59.999998
echo uDate('1544639767.999998')->format('Y-m-d H:i:s.u'), PHP_EOL; // 2018-12-12 18:36:07.999998  
  • floor函数可以简单地提取整数部分,因为它总是四舍五入为“最近的最小整数”。