Como posso analisar uma string de tempo contendo milissegundos com python?

204

Eu sou capaz de analisar seqüências de caracteres contendo data / hora com 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)

Como posso analisar uma seqüência de tempo que contém milissegundos?

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

Respostas:

318

O Python 2.6 adicionou uma nova macro strftime / strptime %f, que faz microssegundos. Não tenho certeza se isso está documentado em qualquer lugar. Mas se você estiver usando o 2.6 ou 3.0, poderá fazer o seguinte:

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

Edit: Eu nunca realmente trabalho com o timemódulo, então não percebi isso no começo, mas parece que o time.struct_time não armazena milissegundos / microssegundos. Você pode estar usando melhor datetimeassim:

>>> 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
fonte
4
Obrigado docs.python.org/library/datetime.html : Novo na versão 2.6: os objetos time e datetime suportam um código de formato% f que se expande para o número de microssegundos no objeto, preenchido com zero à esquerda para seis lugares.
Ilkinulas 30/03/09
5
Woa posso dizer que os documentos do Python precisam ser atualizados. Os documentos do módulo de tempo não falam nada %f.
phunehehe
14
Os documentos do Python, na versão 2.7.3, são um pouco enganadores. Por strptime,% f pode realmente representar qualquer número de casas decimais, e não apenas 6, como seria de esperar em microssegundos. Portanto, o código acima analisaria 32.123 segundos e armazenaria como 123.000µs, que é o que queremos.
Michael Scheper
9
O número %fé preenchido com zeros à direita (não à esquerda!) Com 6 casas decimais. 1 é analisado para 100000, 12 é analisado para 120000 e 1234567 produzValueError: unconverted data remains: 7
user443854
17
Sou apenas eu ou a pergunta era sobre milissegundos, não microssegundos?
Purrell
12

Sei que essa é uma pergunta mais antiga, mas ainda estou usando o Python 2.4.3 e precisava encontrar uma maneira melhor de converter a sequência de dados em um datetime.

A solução se datetime não suportar% f e sem precisar de uma tentativa / exceto é:

    (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 

Isso funciona para a string de entrada "2010-10-06 09: 42: 52.266000"

Andrew Stern
fonte
1
dt.replace(microsecond=int(mSecs))
haridsv
Isso se aplica ao Python 2.5 e versões anteriores. Python 2.6 suporta strptime '% f'
smci
4

Para fornecer o código ao qual a resposta do nstehr se refere (de sua fonte ):

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

A resposta DNS acima está realmente incorreta. O SO está perguntando sobre milissegundos, mas a resposta é para microssegundos. Infelizmente, o Python`s não possui uma diretiva para milissegundos, apenas microssegundos (consulte o documento ), mas você pode contornar isso adicionando três zeros no final da string e analisando a string como microssegundos, algo como:

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

onde time_stré formatado como 30/03/09 16:31:32.123.

Espero que isto ajude.

Rafid
fonte
2
Pensei a mesma coisa inicialmente, mas veja os comentários sobre a resposta e os documentos . É à esquerda com zeros à esquerda microssegundos, então .123é corretamente interpretada como 123.000 microssegundos
aschmied
1

Meu primeiro pensamento foi tentar transmiti-lo '30 / 03/09 16: 31: 32.123 '(com um ponto em vez de dois pontos entre os segundos e os milissegundos.) Mas isso não funcionou. Uma rápida olhada nos documentos indica que os segundos fracionários são ignorados em qualquer caso ...

Ah, diferenças de versão. Isso foi relatado como um bug e agora no 2.6+ você pode usar "% S.% f" para analisá-lo.

MarkusQ
fonte
Isso não funciona; time.strptime simplesmente não faz milissegundos.
DNS
1

das listas de discussão em python: analisando o segmento de milissegundos . Há uma função postada lá que parece fazer o trabalho, embora, como mencionado nos comentários do autor, seja uma espécie de hack. Ele usa expressões regulares para lidar com a exceção levantada e, em seguida, faz alguns cálculos.

Você também pode tentar fazer as expressões regulares e os cálculos antecipadamente, antes de passar para strptime.

nstehr
fonte
Sim, eu conheço esse tópico. Mas estou procurando uma maneira mais simples. existe algum módulo na lib python padrão que gaste tempo analisando com milissegundos?
Ilkinulas 30/03/09
1

Para python 2 eu fiz isso

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

imprime o tempo "% H:% M:% S", divide o time.time () em duas substrings (antes e depois do.) xxxxxxx.xx e como .xx são meus milissegundos, adiciono a segunda substring ao meu "% H:% M:% S "

espero que faça sentido :) Exemplo de saída:

13: 31: 21.72 Piscar 01


13: 31: 21.81 FIM DO INTERVALO 01


13: 31: 26.3 Piscar 01


13: 31: 26.39 FIM DO INTERVALO 01


13: 31: 34.65 Pista inicial 01


Papatrexas
fonte