Як я можу проаналізувати часовий рядок, що містить у ньому мілісекунди, за допомогою python?


204

Я вмію розбирати рядки, що містять дату / час, з 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)

Як я можу проаналізувати часовий рядок, що містить мілісекунди?

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

Відповіді:


318

Python 2.6 додав новий макрос строфінгу / strptime %f, який робить мікросекунди. Не впевнений, чи це десь задокументовано. Але якщо ви використовуєте 2.6 або 3.0, ви можете зробити це:

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

Редагувати: Я ніколи не працюю з timeмодулем, тому спочатку цього не помічав, але, здається, що time.struct_time насправді не зберігає мілісекунди / мікросекунди. Можливо, вам буде краще користуватися datetimeтаким чином:

>>> 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
Спасибі docs.python.org/library/datetime.html : Нове у версії 2.6: об'єкти часу та дати підтримують код формату% f, який розширюється на кількість мікросекунд у об’єкті, з нульовим накладеним зліва на шість місць.
ilkinulas

5
Вау, я можу сказати, що документи Python потребують оновлення. Документи для часового модуля нічого не говорять %f.
phunehehe

14
Документи Python, як і версії 2.7.3, трохи вводять в оману. У режимі strptime% f може фактично представляти будь-яку кількість десяткових знаків, а не лише 6, як можна очікувати за мікросекунди. Отже, наведений вище код розбере 32.123 секунди і збереже його як 123000 мкс, чого ми хочемо.
Майкл Шепер

9
Число у %fзафіксовано нулями праворуч (не ліворуч!) До 6 знаків після коми. 1 розбирається на 100000, 12 розбирається на 120000, а 1234567 виробляєValueError: unconverted data remains: 7
user443854

17
Це тільки я або було питання про мілісекунди, а не мікросекунди?
Перрелл

12

Я знаю, що це питання старіше, але я все ще використовую Python 2.4.3, і мені потрібно було знайти кращий спосіб перетворення рядка даних у дату.

Рішення, якщо timetime не підтримує% f і не потребує спроби / за винятком:

    (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 

Це працює для вхідного рядка "2010-10-06 09: 42: 52.266000"


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

Це стосується Python 2.5 та новіших версій. Python 2.6 підтримує strptime '% f'
smci

4

Щоб вказати код, на який посилається відповідь nstehrйого джерела ):

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

Відповідь DNS, наведена вище , насправді невірна. SO задає питання про мілісекунди, але відповідь - за мікросекунди. На жаль, Python`s не має директиви на мілісекунди, а лише на мікросекунди (див. Doc ), але ви можете її обійти, додавши три нулі в кінці рядка і проаналізувавши рядок як мікросекунди, щось на зразок:

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

де time_strформатується як 30/03/09 16:31:32.123.

Сподіваюсь, це допомагає.


2
Я думав те саме, що спочатку, але дивіться коментарі до відповіді та док . Це лівий нульовий прокладені мікросекунди, так .123правильно інтерпретуються як 123000 мікросекунд
aschmied

1

Перша моя думка полягала в тому, щоб спробувати пропустити це '30 / 03/09 16: 31: 32.123 '(з періодом замість двокрапки між секундами і мілісекундами.) Але це не вийшло. Швидкий погляд на документи вказує на те, що дробові секунди в будь-якому випадку ігноруються ...

Ах, різниці версій. Про це повідомлялося як про помилку, і тепер у версії 2.6+ ви можете використовувати "% S.% f" для розбору.


Це не працює; time.strptime просто не робить мілісекунд.
DNS

1

зі списків розсилки python: розбір мілісекундних потоків . Існує функція, розміщена там, яка, схоже, виконує роботу, хоча, як згадується в коментарях автора, це свого роду злом. Він використовує регулярні вирази для обробки винятку, який стає підвищеним, а потім виконує деякі обчислення.

Ви також можете спробувати виконати регулярні вирази та обчислення наперед, перед тим, як передати його до strptime.


так, я знаю цю нитку. Але я шукаю більш простий спосіб. Чи є модуль в стандартній вкладці python, який робить час розбору з мілісекундами?
ilkinulas

1

Для python 2 я це зробив

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

він друкує час "% H:% M:% S", розбиває time.time () на дві підрядки (до і після.) xxxxxxx.xx і оскільки .xx - це мої мілісекунди, я додаю другу підрядку до моєї "% H:% M:% S "

сподіваюся, що це має сенс :) Приклад виводу:

13: 31: 21,72 Мигайте 01


13: 31: 21,81 КІН БІЛЬКИ 01


13: 31: 26.3 Мигніть 01


13: 31: 26.39 КІН БІЛЬКИ 01


13: 31: 34,65 Стартова смуга 01


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.