from - python datetime: redondear/recortar el número de dígitos en microsegundos
python strftime (7)
Aquí está mi solución usando regexp:
import re
# Capture 6 digits after dot in a group.
regexp = re.compile(r''/.(/d{6})'')
def to_splunk_iso(dt):
"""Converts the datetime object to Splunk isoformat string."""
# 6-digits string.
microseconds = regexp.search(dt.isoformat()).group(1)
return regexp.sub(''.%d'' % round(float(microseconds) / 1000), dt.isoformat())
Actualmente estoy registrando cosas y estoy usando mi propio formateador con un formatTime personalizado ():
def formatTime(self, _record, _datefmt):
t = datetime.datetime.now()
return t.strftime(''%Y-%m-%d %H:%M:%S.%f'')
Mi problema es que los microsegundos,% f, son seis dígitos. ¿Hay alguna forma de escupir menos dígitos, como los tres primeros dígitos de los microsegundos?
Arreglando la solución propuesta en base a los comentarios de Pablojim :
from datetime import datetime dt = datetime.now() dt_round_microsec = round(dt.microsecond/1000) #number of zeroes to round dt = dt.replace(microsecond=dt_round_microsec)
Edición: Como algunos lo señalan en los comentarios a continuación, el redondeo de esta solución (y la anterior) presenta problemas cuando el valor de microsegundos alcanza 999500, ya que 999.5 se redondea a 1000 (desbordamiento).
Si no es necesario volver a implementar Strftime para admitir el formato que queremos (el potencial desbordamiento causado por el redondeo debería propagarse hasta segundos, luego minutos, etc.), es mucho más simple truncar hasta los primeros 3 dígitos como se indica en el respuesta aceptada, o usando algo como:
''{:03}''.format(int(999999/1000))
- Respuesta original conservada a continuación -
En mi caso, estaba tratando de formatear una marca de datos con milisegundos formateados como ''ddd''. La solución que terminé usando para obtener milisegundos fue usar el atributo de microsecond
del objeto datetime
, dividirlo por 1000.0, rellenarlo con ceros si es necesario y redondearlo con formato. Se parece a esto:
''{:03.0f}''.format(datetime.now().microsecond / 1000.0)
# Produces: ''033'', ''499'', etc.
Este método permite una precisión flexible y consumirá todo el valor de microsegundos si especifica una precisión demasiado grande.
def formatTime(self, _record, _datefmt, precision=3):
dt = datetime.datetime.now()
us = str(dt.microsecond)
f = us[:precision] if len(us) > precision else us
return "%d-%d-%d %d:%d:%d.%d" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, int(f))
Este método implementa el redondeo a 3 lugares decimales:
import datetime
from decimal import *
def formatTime(self, _record, _datefmt, precision=''0.001''):
dt = datetime.datetime.now()
seconds = float("%d.%d" % (dt.second, dt.microsecond))
return "%d-%d-%d %d:%d:%s" % (dt.year, dt.month, dt.day, dt.hour, dt.minute,
float(Decimal(seconds).quantize(Decimal(precision), rounding=ROUND_HALF_UP)))
strftime
usar el método strftime
propósito porque preferiría no modificar un objeto datetime completamente serializado sin volverlo a validar. De esta forma también se muestran los datos internos de la fecha en caso de que desee modificarla más.
En el ejemplo de redondeo, tenga en cuenta que la precisión se basa en cadenas para el módulo Decimal
.
Este método siempre debe devolver una marca de tiempo que se vea exactamente como esta (con o sin la zona horaria dependiendo de si el objeto dt
entrada contiene uno):
2016-08-05T18: 18: 54.776 + 0000
Toma un objeto datetime
como entrada (que puede producir con datetime.datetime.now()
). Para obtener la zona horaria como en la salida de mi ejemplo, deberá import pytz
y pasar datetime.datetime.now(pytz.utc)
.
import pytz, datetime
time_format(datetime.datetime.now(pytz.utc))
def time_format(dt):
return "%s:%.3f%s" % (
dt.strftime(''%Y-%m-%dT%H:%M''),
float("%.3f" % (dt.second + dt.microsecond / 1e6)),
dt.strftime(''%z'')
)
Noté que algunos de los otros métodos anteriores omitirían el cero final si hubiera uno (por ejemplo, 0.870
convirtió en 0.87
) y esto estaba causando problemas para el analizador en el que estaba introduciendo estas marcas de tiempo. Este método no tiene ese problema.
La forma más sencilla sería utilizar el corte para cortar los tres últimos dígitos de los microsegundos:
def format_time():
t = datetime.datetime.now()
s = t.strftime(''%Y-%m-%d %H:%M:%S.%f'')
return s[:-3]
Si realmente quieres redondear el número en lugar de solo cortar, es un poco más de trabajo pero no es horrible:
def format_time():
t = datetime.datetime.now()
s = t.strftime(''%Y-%m-%d %H:%M:%S.%f'')
tail = s[-7:]
f = round(float(tail), 3)
temp = "%.3f" % f
return "%s%s" % (s[:-7], temp[1:])
Una solución fácil que debería funcionar en todos los casos:
from datetime import datetime
dt = datetime.now()
dt_round_microsec = round(dt.microsecond/1000) #number of zeroes to round
dt = dt.replace(microsecond=dt_round_microsec)
Básicamente, primero redondeas manualmente el objeto de fecha y luego puedes recortar los microsegundos de forma segura.