Python ile milisaniye içeren bir zaman dizesini nasıl ayrıştırabilirim?


205

Time.strptime ile tarih / saat içeren dizeleri ayrıştırabiliyorum

>>> import time
>>> time.strptime('30/03/09 16:31:32', '%d/%m/%y %H:%M:%S')
(2009, 3, 30, 16, 31, 32, 0, 89, -1)

Milisaniye içeren bir zaman dizesini nasıl ayrıştırabilirim?

>>> time.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/_strptime.py", line 333, in strptime
    data_string[found.end():])
ValueError: unconverted data remains: .123

Yanıtlar:


319

Python 2.6 %f, mikrosaniye yapan yeni bir strftime / strptime makrosu ekledi . Bunun herhangi bir yerde belgelenip belgelenmediğinden emin değilim. Ancak 2.6 veya 3.0 kullanıyorsanız, bunu yapabilirsiniz:

time.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')

Düzenleme: Ben asla gerçekten timemodül ile çalışmak , bu yüzden ilk başta fark etmedi, ama time.struct_time aslında milisaniye / mikrosaniye depolamak görünmüyor. Aşağıdaki datetimegibi kullanarak daha iyi olabilirsiniz :

>>> from datetime import datetime
>>> a = datetime.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')
>>> a.microsecond
123000

4
Teşekkürler docs.python.org/library/datetime.html : 2.6 sürümündeki yenilikler : zaman ve datetime nesneleri, soldaki altı yere sıfır dolgulu, nesnedeki mikrosaniye sayısına kadar genişleyen% f biçim kodunu destekler.
ilkinulas

5
Woa Python belgelerinin güncellenmesi gerektiğini söyleyebilirim. Zaman modülü için dokümanlar hakkında hiçbir şey söylemez %f.
phunehehe

14
2.7.3 sürümünden itibaren Python belgeleri biraz yanıltıcıdır. Strptime için,% f, mikrosaniye için beklendiği gibi, sadece 6 değil, herhangi bir sayıda ondalık basamağı temsil edebilir. Yani yukarıdaki kod 32.123 saniyeyi ayrıştırır ve 123.000µs olarak saklardı, bu bizim istediğimiz şey.
Michael Scheper

9
İçindeki sayı sağda%f sıfırlarla (solda değil!) 6 ondalık basamağa kadar doldurulur . 1 ValueError: unconverted data remains: 7
100000'e

18
Sadece ben miyim yoksa mikrosaniye değil, milisaniye ile ilgili soru muydu?
Purrell

12

Bu eski bir soru olduğunu biliyorum ama hala Python 2.4.3 kullanıyorum ve veri dizesini bir datetime dönüştürmek için daha iyi bir yol bulmak gerekiyordu.

Tarihsaat% f'yi desteklemiyorsa ve bir deneme / hariç tutmaya gerek kalmadan çözüm:

    (dt, mSecs) = row[5].strip().split(".") 
    dt = datetime.datetime(*time.strptime(dt, "%Y-%m-%d %H:%M:%S")[0:6])
    mSeconds = datetime.timedelta(microseconds = int(mSecs))
    fullDateTime = dt + mSeconds 

Bu, "2010-10-06 09: 42: 52.266000" giriş dizesi için geçerlidir


1
dt.replace(microsecond=int(mSecs))
haridsv

Bu Python 2.5 ve öncesi için geçerlidir. Python 2.6 '% f'
hızını

4

Nstehr yanıtının başvurduğu kodu vermek için ( kaynağından ):

def timeparse(t, format):
    """Parse a time string that might contain fractions of a second.

    Fractional seconds are supported using a fragile, miserable hack.
    Given a time string like '02:03:04.234234' and a format string of
    '%H:%M:%S', time.strptime() will raise a ValueError with this
    message: 'unconverted data remains: .234234'.  If %S is in the
    format string and the ValueError matches as above, a datetime
    object will be created from the part that matches and the
    microseconds in the time string.
    """
    try:
        return datetime.datetime(*time.strptime(t, format)[0:6]).time()
    except ValueError, msg:
        if "%S" in format:
            msg = str(msg)
            mat = re.match(r"unconverted data remains:"
                           " \.([0-9]{1,6})$", msg)
            if mat is not None:
                # fractional seconds are present - this is the style
                # used by datetime's isoformat() method
                frac = "." + mat.group(1)
                t = t[:-len(frac)]
                t = datetime.datetime(*time.strptime(t, format)[0:6])
                microsecond = int(float(frac)*1e6)
                return t.replace(microsecond=microsecond)
            else:
                mat = re.match(r"unconverted data remains:"
                               " \,([0-9]{3,3})$", msg)
                if mat is not None:
                    # fractional seconds are present - this is the style
                    # used by the logging module
                    frac = "." + mat.group(1)
                    t = t[:-len(frac)]
                    t = datetime.datetime(*time.strptime(t, format)[0:6])
                    microsecond = int(float(frac)*1e6)
                    return t.replace(microsecond=microsecond)

        raise

2

Yukarıdaki DNS yanıtı aslında yanlış. SO milisaniye soruyor ama cevap mikrosaniye için. Ne yazık ki, Python`s milisaniye için bir direktife sahip değil, sadece mikrosaniye ( dokümana bakınız ), ancak dizenin sonuna üç sıfır ekleyerek ve dizeyi mikrosaniye olarak ayrıştırarak bu sorunu çözebilirsiniz :

datetime.strptime(time_str + '000', '%d/%m/%y %H:%M:%S.%f')

nerede time_strbiçimlendirilir 30/03/09 16:31:32.123.

Bu yardımcı olur umarım.


3
Başlangıçta aynı şeyi düşündüm, ancak cevap ve dokümanlar hakkındaki yorumlara bakın . Bu oluyor sol sıfır getirilmiş mikrosaniye, yani .123doğru 123000 mikrosaniye olarak yorumlanır
aschmied

1

İlk düşüncem onu ​​'30/03/09 16: 31: 32.123' (saniye ve milisaniye arasında iki nokta üst üste yerine bir nokta ile) geçmeyi denemekti. Ama bu işe yaramadı. Dokümanlara hızlı bir bakış, her durumda kesirli saniyelerin yok sayıldığını gösterir ...

Ah, sürüm farklılıkları. Bu bir hata olarak bildirildi ve şimdi 2.6 + 'da ayrıştırmak için "% S.% f" kullanabilirsiniz.


Bu işe yaramıyor; time.strptime sadece milisaniye yapmaz.
DNS

1

python posta listelerinden: milisaniye iş parçacığını ayrıştırma . Yazarın yorumlarında belirtildiği gibi bir tür hack olmasına rağmen, orada yayınlanan işi yapan bir işlev var. Yükselen istisnayı işlemek için düzenli ifadeler kullanır ve sonra bazı hesaplamalar yapar.

Ayrıca, strptime'a geçmeden önce düzenli ifadeleri ve hesaplamaları önceden yapmayı deneyebilirsiniz.


evet, o iş parçacığını biliyorum. Ama daha basit bir yol arıyorum. Standart python lib'inde zamanın milisaniye ile ayrıştırılmasını sağlayan herhangi bir modül var mı?
ilkinulas

1

Python 2 için bunu yaptım

print ( time.strftime("%H:%M:%S", time.localtime(time.time())) + "." + str(time.time()).split(".",1)[1])

"% H:% M:% S" zamanını yazdırır, time.time () öğesini iki alt dizeye böler (.'den önce ve sonra). xxxxxxx.xx ve .xx milisaniyelerim olduğu için ikinci alt dizgimi benim "% H:% M:% S"

mantıklı geliyor :) Örnek çıktı:

13: 31: 21.72 Göz kırpma 01


13: 31: 21.81 BLINK 01 SONU


13: 31: 26.3 Göz kırpma 01


13: 31: 26.39 BLINK 01 SONU


13: 31: 34.65 Başlangıç ​​Şeridi 01


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.