web-dev-qa-db-fra.com

date/heure: nombre de chiffres arrondi/ajusté en microsecondes

Actuellement, je suis en train de consigner des données et j'utilise mon propre formateur avec un formatTime() personnalisé:

def formatTime(self, _record, _datefmt):
    t = datetime.datetime.now()
    return t.strftime('%Y-%m-%d %H:%M:%S.%f')

Mon problème est que les microsecondes, %f, sont six chiffres. Est-il possible de cracher moins de chiffres, comme les trois premiers chiffres des microsecondes?

27
Parham

Le moyen le plus simple serait d’utiliser le découpage en tranches pour couper les trois derniers chiffres des microsecondes:

def format_time():
    t = datetime.datetime.now()
    s = t.strftime('%Y-%m-%d %H:%M:%S.%f')
    return s[:-3]

Si vous voulez réellement arrondir le nombre plutôt que de simplement couper, c'est un peu plus de travail mais pas 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:])
34
steveha

Cette méthode doit toujours renvoyer un horodatage qui ressemble exactement à ceci (avec ou sans le fuseau horaire, selon que l'objet dt en entrée en contient un):

2016-08-05T18: 18: 54.776 + 0000

Il faut un objet datetime en entrée (que vous pouvez produire avec datetime.datetime.now()). Pour obtenir le fuseau horaire comme dans mon exemple de sortie, vous devez import pytz et transmettre 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')
    )   

J'ai remarqué que certaines des méthodes ci-dessus omettaient le zéro final s'il en existait une (par exemple, 0.870 est devenu 0.87) et cela posait problème à l'analyseur syntaxique dans lequel je chargeais ces horodatages. Cette méthode n'a pas ce problème.

2
Eric Herot

Une solution simple qui devrait fonctionner dans tous les cas:

def format_time():
    t = datetime.datetime.now()
    if t.microsecond % 1000 >= 500:  # check if there will be rounding up
        t = t + datetime.timedelta(milliseconds=1)  # manually round up
    return t.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]

Fondamentalement, vous commencez par arrondir manuellement l’objet de date lui-même, puis vous pouvez ajuster les microsecondes en toute sécurité.

1
Abdurrahman

Voici ma solution en utilisant 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())
1
iurii

Cette méthode permet une précision flexible et consomme toute la valeur en microsecondes si vous spécifiez une précision trop 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))

Cette méthode implémente l'arrondi à 3 décimales:

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

J'ai évité d'utiliser la méthode strftime à dessein parce que je préférerais ne pas modifier un objet datetime entièrement sérialisé sans le revalider. Cette façon affiche également les dates internes au cas où vous souhaitez le modifier davantage.

Dans l'exemple d'arrondi, notez que la précision est basée sur une chaîne pour le module Decimal.

1
NuclearPeon

Fixer la solution proposée sur Pablojim Commentaires:

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)
0
gandreoti