Formate uma data e hora em uma sequência de caracteres com milissegundos

169

Eu quero ter uma datetimestring a partir da data em milissegundos. Esse código é típico para mim e estou ansioso para aprender como reduzi-lo.

from datetime import datetime

timeformatted= str(datetime.utcnow())
semiformatted= timeformatted.replace("-","")
almostformatted= semiformatted.replace(":","")
formatted=almostformatted.replace(".","")
withspacegoaway=formatted.replace(" ","")
formattedstripped=withspacegoaway.strip()
print formattedstripped
Jurudocs
fonte
3
Por favor, escreva um título que descreva seu problema e tente manter sua pergunta clara e objetiva.
agf 28/09
Vale a pena mencionar aqui que a precisão extra geralmente é boa. Por exemplo, os Java Instant.parsepodem analisar a representação criada comstrftime('%Y-%m-%dT%H:%M:%S.%fZ')
Jarek Przygódzki 8/17/17

Respostas:

353

Para obter uma sequência de datas com milissegundos (3 casas decimais atrás de segundos), use o seguinte:

from datetime import datetime

print datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]

>>>> OUTPUT >>>>
2020-05-04 10:18:32.926

Nota: Para Python3, printrequer parênteses:

print(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
Jeremy Moritz
fonte
1
Para ser preciso, 2013-08-23 10:18:32.926é a saída de print datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] .
Jaan
3
Observe que, se você quiser usar o import datetimeinvés de from datetime import datetime, precisará usar o seguinte:datetime.datetime.utcnow().strftime("%H:%M:%S.%f")
Luc
17
No caso de microssegundos serem 0, os microsegundos de implementação do Windows 2.7 não são impressos, então apara segundos :(
cabbi
8
Note que este trunca, não rodadas para milissegundos
gens
2
Como menciona Gens, isso não vai dar errado, pois o primeiro número de gotas é> = 5 ?. De fato, se a parte useg é> 999.500, então você nunca vai obter o direito tempo brincando com microssegundos parte
Chris
59

Com o Python 3.6, você pode usar:

from datetime import datetime
datetime.utcnow().isoformat(sep=' ', timespec='milliseconds')

Resultado:

'2019-05-10 09:08:53.155'

Mais informações aqui: https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat

Lorenzo
fonte
Também é útil com o fuso horário: date = datetime (2019,5,10) date_with_tz = pytz.timezone ('Europe / Rome'). Localize (date) date_with_tz.isoformat (sep = 'T', timespec = 'milliseconds') output: '2019-05-10T00: 00: 00.000 + 02: 00'
Ena
Esta é a solução real que deve ser aceita. E o isoformat () é o que eu preciso para exportar para o formato GPX, muito obrigado!
Filip Happy
22
print datetime.utcnow().strftime('%Y%m%d%H%M%S%f')

http://docs.python.org/library/datetime.html#strftime-strptime-behavior

knitti
fonte
13
Para sua informação, imprime microssegundos como os últimos 6 dígitos. Adicione [:-3]ao final para soltar os três últimos dígitos para que ele exiba apenas milissegundos.
precisa saber é o seguinte
5
microssegundos pode ser inferior a 6 dígitos, então [: -3] é imprimir milissegundos erradas
cabbi
13
e se tivermos fuso horário?
ᐅ devrimbaris
1
@ Devrimbaris para check-out do fuso horário Resposta de Lorenzo
Ena
17

A @Cabbi levantou a questão de que, em alguns sistemas, o formato de microssegundos %fpode dar "0", por isso não é portátil simplesmente cortar os últimos três caracteres.

O código a seguir formata cuidadosamente um carimbo de data / hora com milissegundos:

from datetime import datetime
(dt, micro) = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.')
dt = "%s.%03d" % (dt, int(micro) / 1000)
print dt

Saída de exemplo:

2016-02-26 04:37:53.133

Para obter a saída exata que o OP queria, precisamos remover os caracteres de pontuação:

from datetime import datetime
(dt, micro) = datetime.utcnow().strftime('%Y%m%d%H%M%S.%f').split('.')
dt = "%s%03d" % (dt, int(micro) / 1000)
print dt

Saída de exemplo:

20160226043839901
Sam Watkins
fonte
6
Na verdade, o que estou fazendo é: print '% s.% 03d'% (dt.strftime ("% Y-% m-% d% H:% M:% S"), int (dt.microsegundo / 1000 ))
cabbi
2
Concordo com @cabbi, não há necessidade de converter e para trás com cordas e int
caoanan
sim eu concordo também ... :)
Sam Watkins
1
Esta resposta é muito mais precisa e segura do que as outras. Obrigado !
Hunaphu 5/03/19
5

Provavelmente assim:

import datetime
now = datetime.datetime.now()
now.strftime('%Y/%m/%d %H:%M:%S.%f')[:-3]  
# [:-3] => Removing the 3 last characters as %f is for microsecs.
N Fayçal
fonte
O segundo %mdeve ser um %M, porque são minutos, não meses.
Michael Dorner
2

Eu suponho que você quer dizer que você está procurando algo que é mais rápido que datetime.datetime.strftime () e está basicamente retirando os caracteres não-alfa de um timestamp utc.

Sua abordagem é marginalmente mais rápida, e acho que você pode acelerar ainda mais as coisas cortando a corda:

>>> import timeit
>>> t=timeit.Timer('datetime.utcnow().strftime("%Y%m%d%H%M%S%f")','''
... from datetime import datetime''')
>>> t.timeit(number=10000000)
116.15451288223267

>>> def replaceutc(s):
...     return s\
...         .replace('-','') \
...         .replace(':','') \
...         .replace('.','') \
...         .replace(' ','') \
...         .strip()
... 
>>> t=timeit.Timer('replaceutc(str(datetime.datetime.utcnow()))','''
... from __main__ import replaceutc
... import datetime''')
>>> t.timeit(number=10000000)
77.96774983406067

>>> def sliceutc(s):
...     return s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:]
... 
>>> t=timeit.Timer('sliceutc(str(datetime.utcnow()))','''
... from __main__ import sliceutc
... from datetime import datetime''')
>>> t.timeit(number=10000000)
62.378515005111694
Austin Marshall
fonte
@oxtopus Bom trabalho. Pessoalmente, eu não uso timeit mais para simples medição de tempo. É estranho que os rácios de tempos são diferentes com o seu código: 1 - 0,67 - 0,53 e com a minha: 1 - 0,35 - 0,20, para os métodos strftime - substituir - corte
Eyquem
Talvez algo a ver com o str (datetime.datetime.utcnow ()) sendo chamado em cada iteração do teste versus defini-lo uma vez?
Austin Marshall
1
from datetime import datetime
from time import clock

t = datetime.utcnow()
print 't == %s    %s\n\n' % (t,type(t))

n = 100000

te = clock()
for i in xrange(1):
    t_stripped = t.strftime('%Y%m%d%H%M%S%f')
print clock()-te
print t_stripped," t.strftime('%Y%m%d%H%M%S%f')"

print

te = clock()
for i in xrange(1):
    t_stripped = str(t).replace('-','').replace(':','').replace('.','').replace(' ','')
print clock()-te
print t_stripped," str(t).replace('-','').replace(':','').replace('.','').replace(' ','')"

print

te = clock()
for i in xrange(n):
    t_stripped = str(t).translate(None,' -:.')
print clock()-te
print t_stripped," str(t).translate(None,' -:.')"

print

te = clock()
for i in xrange(n):
    s = str(t)
    t_stripped = s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:] 
print clock()-te
print t_stripped," s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:] "

resultado

t == 2011-09-28 21:31:45.562000    <type 'datetime.datetime'>


3.33410112179
20110928212155046000  t.strftime('%Y%m%d%H%M%S%f')

1.17067364707
20110928212130453000 str(t).replace('-','').replace(':','').replace('.','').replace(' ','')

0.658806915404
20110928212130453000 str(t).translate(None,' -:.')

0.645189262881
20110928212130453000 s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:]

O uso do método translate () e slicing executado ao mesmo tempo
translate () apresenta a vantagem de ser utilizável em uma linha

Comparando os tempos com base no primeiro:

1.000 * t.strftime ('% Y% m% d% H% M% S% f')

0,351 * str (t) .replace ('-', ''). Replace (':', ''). Replace ('.', ''). Replace ('', '')

0,198 * str (t) .tradução (Nenhuma, '- :.')

0,194 * s [: 4] + s [5: 7] + s [8:10] + s [11:13] + s [14:16] + s [17:19] + s [20:]

eyquem
fonte
1
Agradável! Isso é realmente mais limpo sem sacrificar o desempenho. str.translate () realmente mais rápido nos meus testes.
Austin Marshall
1

Lidei com o mesmo problema, mas no meu caso, era importante que o milissegundo fosse arredondado e não truncado

from datetime import datetime, timedelta

def strftime_ms(datetime_obj):
    y,m,d,H,M,S = datetime_obj.timetuple()[:6]
    ms = timedelta(microseconds = round(datetime_obj.microsecond/1000.0)*1000)
    ms_date = datetime(y,m,d,H,M,S) + ms
    return ms_date.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
omdaniel
fonte
1
import datetime

# convert string into date time format.

str_date = '2016-10-06 15:14:54.322989'
d_date = datetime.datetime.strptime(str_date , '%Y-%m-%d %H:%M:%S.%f')
print(d_date)
print(type(d_date)) # check d_date type.


# convert date time to regular format.

reg_format_date = d_date.strftime("%d %B %Y %I:%M:%S %p")
print(reg_format_date)

# some other date formats.
reg_format_date = d_date.strftime("%Y-%m-%d %I:%M:%S %p")
print(reg_format_date)
reg_format_date = d_date.strftime("%Y-%m-%d %H:%M:%S")
print(reg_format_date)

<<<<<< SAÍDA >>>>>>>

2016-10-06 15:14:54.322989    
<class 'datetime.datetime'>    
06 October 2016 03:14:54 PM    
2016-10-06 03:14:54 PM    
2016-10-06 15:14:54
Waqas Ali
fonte
1
python -c "from datetime import datetime; print str(datetime.now())[:-3]"
2017-02-09 10:06:37.006
arntg
fonte
0
datetime
t = datetime.datetime.now()
ms = '%s.%i' % (t.strftime('%H:%M:%S'), t.microsecond/1000)
print(ms)
14:44:37.134
Hunaphu
fonte
0

O problema com datetime.utcnow()outras soluções é que elas são lentas.

Uma solução mais eficiente pode se parecer com esta:

def _timestamp(prec=0):
    t = time.time()
    s = time.strftime("%H:%M:%S", time.localtime(t))
    if prec > 0:
        s += ("%.9f" % (t % 1,))[1:2+prec]
    return s

Onde precestaria 3no seu caso (milissegundos).

A função funciona com até 9 casas decimais (observe o número 9na 2ª sequência de formatação).

Se você deseja arredondar a parte fracionária, sugiro construir "%.9f"dinamicamente com o número desejado de casas decimais.

mato
fonte