Как я могу разобрать строку времени, содержащую миллисекунды в нем с 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
ilkinulas
источник

Ответы:

318

В Python 2.6 добавлен новый макрос strftime / 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
DNS
источник
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
Это только у меня или был вопрос о миллисекундах, а не микросекундах?
Purrell
12

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

Решение, если datetime не поддерживает% 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 не имеет директивы для миллисекунд, только микросекунд (см. Документ ), но вы можете обойти это, добавив три нуля в конце строки и проанализировав строку как микросекунды, что-то вроде:

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

где time_strотформатирован как 30/03/09 16:31:32.123.

Надеюсь это поможет.

Рафид
источник
2
Сначала я думал то же самое, но вижу комментарии к ответу и документам . Это микросекунды с .123
добавлением
1

Моей первой мыслью было попытаться передать его «30/03/09 16: 31: 32.123» (с точкой вместо двоеточия между секундами и миллисекундами.) Но это не сработало. Быстрый взгляд на документы показывает, что доли секунды игнорируются в любом случае ...

Ах, различия версий. Это было сообщено как ошибка, и теперь в версии 2.6+ вы можете использовать "% S.% f" для ее анализа.

MarkusQ
источник
Это не работает; time.strptime просто не делает миллисекунд.
DNS
1

из списков рассылки python: разбор миллисекундного потока . Там размещена функция, которая, кажется, выполняет свою работу, хотя, как уже упоминалось в комментариях автора, это своего рода хак. Он использует регулярные выражения для обработки возникающего исключения, а затем выполняет некоторые вычисления.

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

nstehr
источник
да, я знаю эту тему. Но я ищу более простой способ. есть ли в стандартной библиотеке 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 Blink 01


13: 31: 21.81 КОНЕЦ МЫШИ 01


13: 31: 26,3 Мерцание 01


13: 31: 26.39 КОНЕЦ МЫШИ 01


13: 31: 34.65 Стартовая полоса 01


Papatrexas
источник