Soru Mikro saniye ile DateTime


Kodumda kullanıyorum DateTime nesneleri işlemek için nesneler, daha sonra bunları bazı JSON dosyalarına kaydetmek için zaman damgasına dönüştürür.

Bazı nedenlerden ötürü, DateTime (veya yakın bir şey) ile aynı şeylere sahip olmak istiyorum, ancak mikrosaniye hassaslığı ile (JSON dosyalarına eklerken float'a dönersem).

Sorum şu: orada bir PHP nesnesi bu gibi DateTimeama halledebilir mikrosaniye da mı?

Amaç, mikro adımların nesnelerle işlenebilmesidir.

İçinde tarihi () belgeler, DateTime'ın mikrosaniye ile oluşturulabileceğini gösteren bir şey var, ama nasıl olduğunu bulamadım.

Mikroseconds (PHP 5.2.2'de eklenmiştir). Tarihin () her zaman olacağını unutmayın   bir tamsayı parametresi aldığından 000000 oluştururken,   DateTime oluşturulduysa DateTime :: format (), microseconds'ı destekliyor   Mikrosaniye ile.

Bir DateTime nesnesinin zaman damgasını kayan bir değerle ayarlamaya çalıştım (microtime(true)), ama işe yaramıyor (sanırım bu zaman damgasını bir int için dönüştürüyor, mikrosaniye kaybına neden oluyor).

İşte nasıl denedim

$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'));

.4 Burada gördüğünüz gibi dikkate alınmaz ( u microseconds karşılık gelen biçim).

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)

DÜZENLEME: Ben bir DateTime mikrosaniye eklemek için izin veren bu kodu gördüm, ama ben DateTime oluşturmadan önce mikroişlemde bir çok modifikasyon uygulamak gerekir. Bunu çok kullanacağımdan, "mikro-nesne nesnesini" almadan önce mikro adımda mümkün olduğunca az değişiklik yapmak istiyorum.

$d = new DateTime("15-07-2014 18:30:00.111111");

21
2017-11-13 11:12


Menşei


senin sorunun sadece bir vaha oldu, ne arıyorsun? - davejal
Tarihleri, Mikseconds ile aynı olasılıklarla (karşılaştırma, biçimlendirme vb.) Bir DateTime olarak saklamanın etkili bir yolunu arıyorum. - Heru-Luin
bunları bir db olarak saklıyorum, hangisini? - davejal
Depolama bölümü için onları şamandıraya dönüştürür ve bir JSON dosyasına kaydederim. - Heru-Luin


Cevaplar:


İşte, mikro adım içeren bir DateTime nesnesi oluşturmanın çok basit bir yöntemi.

Bu soruyu çok derinden incelemedim, bu yüzden özür dilediğim bir şeyi özlediysem, ama bunu yararlı bulmanızı dilerim.

$date = DateTime::createFromFormat('U.u', microtime(TRUE));
var_dump($date->format('Y-m-d H:i:s.u')); 

Bunu test ettim ve mantıklı görünen bu işi yapmak için başka çeşitli yollar denedim ama bu sadece işe yarayan yöntemdi. Ancak bir sorun vardı, doğru zaman dilimine dönüyordu ama doğru gün bölümünü değil (büyük olasılıkla UTC zamanı yüzünden) İşte yaptığım şey (hala daha basit IMHO gibi görünüyor):

$dateObj = DateTime::createFromFormat('U.u', microtime(TRUE));
$dateObj->setTimeZone(new DateTimeZone('America/Denver'));
var_dump($dateObj->format('Y-m-d H:i:s:u'));

İşte çalışan bir örnek: http://sandbox.onlinephpfunctions.com/code/66f20107d4adf87c90b5c8c914393d4edef180a2 

GÜNCELLEŞTİRME
Yorumlarda belirtildiği gibi, PHP 7.1'den itibaren, Planplan tarafından önerilen yöntem, yukarıda gösterilene üstün görünmektedir.

Yani, tekrar PHP 7.1 ve üstü için yukarıdaki kod yerine aşağıdakileri kullanmak daha iyi olabilir:

$dateObj = DateTime::createFromFormat('0.u00 U', microtime());
$dateObj->setTimeZone(new DateTimeZone('America/Denver'));
var_dump($dateObj->format('Y-m-d H:i:s:u'));

Yukarıdakilerin sadece 7.1 ve üstü PHP sürümleri için çalıştığını lütfen unutmayın. PHP'nin önceki sürümleri, mikroenlemenin yerine 0s döndürecek ve bu nedenle tüm mikro veri verilerini kaybedecek.

İşte her ikisini de gösteren güncel bir sanal alan: http://sandbox.onlinephpfunctions.com/code/a88522835fdad4ae928d023a44b721e392a3295e 

NOT: Yukarıdaki sanal alanı test ederken, Planplan'ın deneyimlediğini belirttiği mikro-darbe (TRUE) hatasını hiç görmedim. Bununla birlikte, güncellenmiş yöntem KristopherWindsor'un önerdiği gibi daha yüksek bir hassasiyet düzeyini kaydetmektedir.


17
2018-05-20 00:42



Nadiren de olsa, microtime (true) sadece bir tamsayı parçasıyla bir float döndürür ve 'U.u' formatı başarısız olur. Bu biraz çirkin, ama bu her zaman DateTime :: createFromFormat ('0.u00 U', microtime ()) ile çalışacaktır; - Planplan
@Planplan Bu, bilmeye değer. Yine de, herhangi bir mikro saniye verisinin kaybolması OP'nin ne istediğine karşı çıkacak gibi görünüyor. Bu yüzden bir hata olarak görmekten şüphe duyuyorum, o zaman bunu konuştuğunuz şekilde yapmak muhtemelen en iyi yaklaşım olacaktır. - MER
@ Planplan'ın çözümü herhangi bir hassasiyet kaybetmez. microtime () aslında, PHP floatlarının kesinliğinden dolayı mikrostime (gerçek) göre daha hassastır. - Kristopher Windsor
@KristopherWindsor Yorumunuz nedeniyle bunu tekrar ziyaret ettim ve PHP sürümü 7.1 ve üstü olduğu sürece tamamen doğru gibi görünüyor. Sandbox.onlinephpfunctions.com 'da gösterildiği gibi PHP'nin erken bir sürümünü kullanırsanız, TÜM mikro saniye verilerini kaybedersiniz (sadece 0'lık bir satır alırsınız). Açıklama için teşekkürler. Cevabı güncelleyeceğim. - MER


PHP DateTime kılavuzundaki bir yanıtı incelemek:

DateTime bölünmüş saniye (mikro saniye veya milisaniye vb.) Desteklemiyor   Bunun neden belgelenmediğini bilmiyorum.   Sınıf kurucusu şikayette bulunmadan kabul eder, ancak atılır.   "2012-07-08 11: 14: 15.638276" gibi bir ipi çekmenin ve nesneyi eksiksiz bir şekilde saklamanın bir yolu yoktur.

Yani, iki dizede tarih matematiği yapamazsınız:

<?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
)

*/
?>

Gerçekten 0.251066 saniye almak istediğinizde geri dönün.


Ancak, bir yanıt alarak İşte:

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

Önerilen ve kullanım dateTime() başvurulan sınıf:

$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).

Referans dateTime() php.net'de: http://php.net/manual/en/datetime.construct.php#


5
2017-11-13 11:17



Bu çözümle, mikro enstalasyonları kolaylıkla kıyaslayamıyorum ve bir mikroişlem ile bir DateTime nesnesi oluşturmak çok fazla kaynak gerektiriyor (bunu bir LOT kullanacağım). - Heru-Luin


/!\ DÜZENLE /!\

Şimdi kullanıyorum https://github.com/briannesbitt/Carbon, bu cevabın geri kalanı sadece tarihsel nedenlerle burada.

END DÜZENİ

Dersi uzatmaya karar verdim DateTime Bana verdiğin ipuçlarını kullanarak.

Kurucu bir şamandıra alır microtime) veya hiçbir şey (bu durumda geçerli "mikro-zaman damgası" ile başlatılacaktır). Ayrıca önemli olan 2 işlevi de geçersiz kıldım: setTimestamp ve getTimestamp.

Ne yazık ki, performans konusunu çözemedim, ancak düşündüğüm kadar yavaş olmadı.

İşte bütün sınıf:

<?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;
    }
}

4
2017-11-25 14:44





Birden çok seçenek var. Ama Ben tarafından zaten verildiği gibi, size başka bir çözüm sunmaya çalışacağım.

Ne tür hesaplamalar yapmak istediğiniz hakkında daha fazla bilgi verdiyseniz, daha fazla değişiklik yapılabilir.

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

veya

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

veya

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

veya

list($usec, $sec) = explode(' ', microtime());
print date('Y-m-d H:i:s', $sec) . $usec;

2
2017-11-13 11:50





/*
 * 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;
  }

0
2017-08-22 20:06





Sorunumu çözdüğümden beri sizinle paylaşmak istiyorum. Php71 +, mikrosaniye hassasiyetine sahiptir, eğer nano hassasiyete dönüştürmek istiyorsanız, bunu 1000 ile çarpın (10 ^ 3).

$nsTimestamp = (int) (new \DateTime())->getTimestamp() * 1000

0
2017-07-30 08:45