PHP DateTime microseconds always returns 0

前端 未结 18 2406
萌比男神i
萌比男神i 2020-12-01 02:55

this code always returns 0 in PHP 5.2.5 for microseconds:

format(\"Y-m-d\\TH:i:s.u\") . \"\\n\";
?>

相关标签:
18条回答
  • 2020-12-01 03:05

    This should be the most flexible and precise:

    function udate($format, $timestamp=null) {
        if (!isset($timestamp)) $timestamp = microtime();
        // microtime(true)
        if (count($t = explode(" ", $timestamp)) == 1) {
            list($timestamp, $usec) = explode(".", $timestamp);
            $usec = "." . $usec;
        }
        // microtime (much more precise)
        else {
            $usec = $t[0];
            $timestamp = $t[1];
        }
        // 7 decimal places for "u" is maximum
        $date = new DateTime(date('Y-m-d H:i:s' . substr(sprintf('%.7f', $usec), 1), $timestamp));
        return $date->format($format);
    }
    echo udate("Y-m-d\TH:i:s.u") . "\n";
    echo udate("Y-m-d\TH:i:s.u", microtime(true)) . "\n";
    echo udate("Y-m-d\TH:i:s.u", microtime()) . "\n";
    /* returns:
    2015-02-14T14:10:30.472647
    2015-02-14T14:10:30.472700
    2015-02-14T14:10:30.472749
    */
    
    0 讨论(0)
  • 2020-12-01 03:05

    Some answers make use of several timestamps, which is conceptually wrong, and overlapping issues may occur: seconds from 21:15:05.999 combined by microseconds from 21:15:06.000 give 21:15:05.000.

    Apparently the simplest is to use DateTime::createFromFormat() with U.u, but as stated in a comment, it fails if there are no microseconds.

    So, I'm suggesting this code:

    function udate($format, $time = null) {
    
        if (!$time) {
            $time = microtime(true);
        }
    
        // Avoid missing dot on full seconds: (string)42 and (string)42.000000 give '42'
        $time = number_format($time, 6, '.', '');
    
        return DateTime::createFromFormat('U.u', $time)->format($format);
    }
    
    0 讨论(0)
  • 2020-12-01 03:12

    date_create

    time: String in a format accepted by strtotime(), defaults to "now".

    strtotime

    time: The string to parse, according to the GNU » Date Input Formats syntax. Before PHP 5.0.0, microseconds weren't allowed in the time, since PHP 5.0.0 they are allowed but ignored.

    0 讨论(0)
  • 2020-12-01 03:20

    This function pulled from http://us3.php.net/date

    function udate($format, $utimestamp = null)
    {
        if (is_null($utimestamp))
            $utimestamp = microtime(true);
    
        $timestamp = floor($utimestamp);
        $milliseconds = round(($utimestamp - $timestamp) * 1000000);
    
        return date(preg_replace('`(?<!\\\\)u`', $milliseconds, $format), $timestamp);
    }
    
    echo udate('H:i:s.u'); // 19:40:56.78128
    

    Very screwy you have to implement this function to get "u" to work... :\

    0 讨论(0)
  • 2020-12-01 03:22
    \DateTime::createFromFormat('U.u', microtime(true));
    

    Will give you (at least on most systems):

    object(DateTime)(
      'date' => '2015-03-09 17:27:39.456200',
      'timezone_type' => 3,
      'timezone' => 'Australia/Darwin'
    )
    

    But there is a loss of precision because of PHP float rounding. It's not truly microseconds.

    Update

    This is probably the best compromise of the createFromFormat() options, and provides full precision.

    \DateTime::createFromFormat('0.u00 U', microtime());
    

    gettimeofday()

    More explicit, and maybe more robust. Solves the bug found by Xavi.

    $time = gettimeofday(); 
    \DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
    
    0 讨论(0)
  • 2020-12-01 03:22

    Inside of an application I am writing I have the need to set/display microtime on DateTime objects. It seems the only way to get the DateTime object to recognize microseconds is to initialize it with the time in format of "YYYY-MM-DD HH:MM:SS.uuuuuu". The space in between the date and time portions can also be a "T" as is usual in ISO8601 format.

    The following function returns a DateTime object initialized to the local timezone (code can be modified as needed of course to suit individual needs):

    // Return DateTime object including microtime for "now"
    function dto_now()
    {
        list($usec, $sec) = explode(' ', microtime());
        $usec = substr($usec, 2, 6);
        $datetime_now = date('Y-m-d H:i:s\.', $sec).$usec;
        return new DateTime($datetime_now, new DateTimeZone(date_default_timezone_get()));
    }
    
    0 讨论(0)
提交回复
热议问题