Bagaimana saya bisa menguraikan string waktu yang mengandung milidetik di dalamnya dengan python?

204

Saya dapat mengurai string yang berisi tanggal / waktu dengan time.strptime

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

Bagaimana saya bisa menguraikan string waktu yang berisi milidetik?

>>> 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
ilkinulas
sumber

Jawaban:

318

Python 2.6 menambahkan strftime / strptime macro baru %f, yang melakukan microseconds. Tidak yakin apakah ini didokumentasikan di mana saja. Tetapi jika Anda menggunakan 2.6 atau 3.0, Anda dapat melakukan ini:

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

Sunting: Saya tidak pernah benar-benar bekerja dengan timemodul, jadi saya tidak memperhatikan ini pada awalnya, tetapi tampaknya time.struct_time tidak benar-benar menyimpan milidetik / mikrodetik. Anda mungkin lebih baik menggunakan datetime, seperti ini:

>>> from datetime import datetime
>>> a = datetime.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')
>>> a.microsecond
123000
DNS
sumber
4
Terima kasih docs.python.org/library/datetime.html : Baru dalam versi 2.6: objek waktu dan datetime mendukung kode format% f yang memperluas ke jumlah mikrodetik dalam objek, nol-empuk di sebelah kiri ke enam tempat.
ilkinulas
5
Woa saya dapat memberitahu Python docs perlu memperbarui. Dokumen untuk modul waktu tidak mengatakan apa-apa %f.
phunehehe
14
Dokumen Python, pada versi 2.7.3, agak menyesatkan. Untuk strptime,% f sebenarnya dapat mewakili sejumlah tempat desimal, bukan hanya 6, seperti yang mungkin diharapkan untuk mikrodetik. Jadi kode di atas akan mengurai 32,123 detik dan menyimpannya sebagai 123.000 μs, yang kita inginkan.
Michael Scheper
9
Angka dalam %fdiisi dengan nol di sebelah kanan (bukan kiri!) Ke 6 tempat desimal. 1 diurai menjadi 100000, 12 diurai ke 120000, dan 1234567 menghasilkanValueError: unconverted data remains: 7
user443854
17
Apakah hanya saya atau pertanyaan tentang milidetik, bukan mikrodetik?
Purrell
12

Saya tahu ini adalah pertanyaan yang lebih lama tetapi saya masih menggunakan Python 2.4.3 dan saya perlu menemukan cara yang lebih baik untuk mengubah string data ke datetime.

Solusi jika datetime tidak mendukung% f dan tanpa perlu mencoba / kecuali adalah:

    (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 

Ini berfungsi untuk string input "2010-10-06 09: 42: 52.266000"

Andrew Stern
sumber
1
dt.replace(microsecond=int(mSecs))
haridsv
Ini berlaku untuk Python 2.5 dan sebelumnya. Python 2.6 mendukung strptime '% f'
smci
4

Untuk memberikan kode yang mengacu pada jawaban nstehr (dari sumbernya ):

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
Phil H
sumber
2

Jawaban DNS di atas sebenarnya salah. SO bertanya tentang milidetik tetapi jawabannya adalah untuk mikrodetik. Sayangnya, Python `s tidak memiliki arahan untuk milidetik, hanya mikrodetik (lihat doc ), tetapi Anda bisa mengatasinya dengan menambahkan tiga nol di akhir string dan menguraikan string sebagai mikrodetik, sesuatu seperti:

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

di mana time_strdiformat seperti 30/03/09 16:31:32.123.

Semoga ini membantu.

Rafid
sumber
2
Awalnya saya memikirkan hal yang sama, tetapi melihat komentar pada jawaban dan dokumen . Ini mikrodetik kiri-nol-empuk , jadi .123ditafsirkan dengan benar sebagai 123.000 mikrodetik
aschmied
1

Pikiran pertama saya adalah mencoba melewatinya '30 / 03/09 16: 31: 32.123 '(dengan titik bukannya titik dua antara detik dan milidetik.) Tapi itu tidak berhasil. Pandangan sekilas ke dokumen menunjukkan bahwa detik fraksional diabaikan dalam hal apa pun ...

Ah, perbedaan versi. Ini dilaporkan sebagai bug dan sekarang di 2.6+ Anda dapat menggunakan "% S.% f" untuk menguraikannya.

MarkusQ
sumber
Itu tidak berhasil; time.strptime tidak hanya melakukan milidetik.
DNS
1

dari milis python: parsing thread milidetik . Ada fungsi yang diposting di sana yang tampaknya menyelesaikan pekerjaan, meskipun seperti yang disebutkan dalam komentar penulis itu adalah jenis peretasan. Ini menggunakan ekspresi reguler untuk menangani pengecualian yang muncul, dan kemudian melakukan beberapa perhitungan.

Anda juga dapat mencoba melakukan ekspresi dan perhitungan reguler di depan, sebelum meneruskannya ke strptime.

nstehr
sumber
ya, saya tahu utas itu. Tetapi saya mencari cara yang lebih sederhana. apakah ada modul di lib python standar yang membuat waktu parsing dengan milidetik?
ilkinulas
1

Untuk python 2 saya melakukan ini

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

ia mencetak waktu "% H:% M:% S", membagi time.time () menjadi dua substring (sebelum dan sesudah.) xxxxxxx.xx dan karena .xx adalah milidetik saya, saya menambahkan substring kedua ke ""% saya. H:% M:% S "

harap masuk akal :) Contoh output:

13: 31: 21.72 Berkedip 01


13: 31: 21.81 AKHIR BLINK 01


13: 31: 26.3 Berkedip 01


13: 31: 26.39 AKHIR BLINK 01


13: 31: 34.65 Memulai Jalur 01


Papatrexas
sumber