DateTime с микросекундами для отрицательных временных отметок (<1970) - PullRequest
0 голосов
/ 12 декабря 2018

Как правильно создать экземпляр DateTime из метки времени Unix с микросекундами?

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 diff в метке времени дает 2s-2us diff в общей сложности.
Я считаю, что это правильнорезультат 1965-12-03 23:59:00.000002.

Как мне достичь этого удобным способом, без ручного пересчета для отрицательных временных меток?


Может быть, я всегда должен интерпретировать формат 'Uu' как 'U + 0.u'значение?
Я имею в виду u это не часть микросекунд, а положительная разница от целой части?

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Вы можете использовать что-то вроде этого, чтобы найти строку времени в правильном формате.

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;
    }
}
0 голосов
/ 12 декабря 2018

Хорошо, тогда мое решение будет таким:

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 Функция может извлечь простую целую часть, потому что она всегда округляется до "ближайшего наименьшего целого числа".
0 голосов
/ 12 декабря 2018

Один из способов сделать это - принудительно вычислить микросекунды, предполагая, что у вас отрицательная временная метка:

$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 будет неправильной, поэтому в этом случае она не будет использоваться.

Не уверен, что это будет работать для каждого сценария, любое предложение будет с благодарностью принято.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...