datetime:舍入/修剪位数,以微秒为单位

时间:2012-06-14 19:38:58

标签: python datetime formatter

目前我正在记录内容,我正在使用自己的格式化程序和自定义formatTime()

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

我的问题是微秒%f是六位数。无论如何都要吐出更少的数字,比如微秒的前三位数?

11 个答案:

答案 0 :(得分:38)

最简单的方法是使用切片来切断微秒的最后三位数字:

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

如果你想要实际数字而不仅仅是劈砍,那么它的工作要多一些,但并不可怕:

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

答案 1 :(得分:2)

编辑:正如一些人在下面的评论中指出的那样,当微秒值达到999500时,这个解决方案(以及上面的那个)的四舍五入会引入问题,因为999.5被舍入到1000(溢出)。

没有重新实现strftime以支持我们想要的格式(由舍入引起的潜在溢出需要传播到秒,然后是几分钟等),将前截断为前3位数更简单在接受的答案中概述,或使用类似的东西:

'{:03}'.format(int(999999/1000))

- 保留下面的原始答案 -

在我的情况下,我试图格式化一个格式为'ddd'的毫秒的日期戳。我最终用来获得毫秒的解决方案是使用microsecond对象的datetime属性,除以1000.0,必要时用零填充,然后用格式对其进行舍入。它看起来像这样:

'{:03.0f}'.format(datetime.now().microsecond / 1000.0)
# Produces: '033', '499', etc.

答案 2 :(得分:2)

此方法应始终返回一个看起来与此完全相同的时间戳(根据输入的dt对象是否包含时区,有或没有时区):

<强> 2016-08-05T18:18:54.776 + 0000

它需要datetime个对象作为输入(您可以使用datetime.datetime.now()生成)。要获得我的示例输出中的时区,您需要import pytz并传递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')
    )   

我注意到上面的其他一些方法如果有一个(例如0.870成为0.87)就会省略尾随零,这会导致我将这些时间戳输入的解析器出现问题。这种方法没有这个问题。

答案 3 :(得分:2)

您可以从微秒中减去当前日期时间。

d = datetime.datetime.now()
current_time = d - datetime.timedelta(microseconds=d.microsecond)

这会将 2021-05-14 16:11:21.916229 变成 2021-05-14 16:11:21

答案 4 :(得分:1)

此方法允许灵活的精度,如果指定的精度太高,将消耗整个微秒值。

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

此方法实现舍入到3个小数位:

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方法,因为我宁愿不修改完全序列化的日期时间对象而不重新验证它。这种方式还会显示日期内部结构,以防您想要进一步修改它。

在舍入示例中,请注意Decimal模块的精度是基于字符串的。

答案 5 :(得分:1)

以下是我使用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())

答案 6 :(得分:1)

适用于所有情况的简单解决方案:

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]

基本上,您首先需要对日期对象本身进行手动舍入,然后可以安全地修剪微秒。

答案 7 :(得分:1)

从 Python 3.6 开始,该语言内置了此功能:

def format_time():
    t = datetime.datetime.now()
    s = t.isoformat(timespec='milliseconds')
    return s

答案 8 :(得分:0)

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

答案 9 :(得分:0)

如果曾经想获得星期几(即“星期日”)及其结果,则切片“ [:-3]”将不起作用。那时您可以选择

dt = datetime.datetime.now()
print("{}.{:03d} {}".format(dt.strftime('%Y-%m-%d %I:%M:%S'), dt.microsecond//1000, dt.strftime("%A")))

#Output: '2019-05-05 03:11:22.211 Sunday'

%H-24小时格式

%I-12小时格式

谢谢

答案 10 :(得分:0)

在这里添加我的 2 美分,因为这种方法将允许您编写微秒格式,就像在 c 样式中编写浮点数一样。它利用了它们都使用 %f 的优势。

import datetime
import re

def format_datetime(date, format):
    """Format a ``datetime`` object with microsecond precision.
       Pass your microsecond as you would format a c-string float.
       e.g "%.3f"

       Args:
            date (datetime.datetime): You input ``datetime`` obj.
            format (str): Your strftime format string.

        Returns:
            str: Your formatted datetime string.
    """
    # We need to check if formatted_str contains "%.xf" (x = a number) 
    float_format = r"(%\.\d+f)"
    has_float_format = re.search(float_format, format)
    if has_float_format:
        # make microseconds be decimal place. Might be a better way to do this
        microseconds = date.microsecond
        while int(microseconds):  # quit once it's 0
            microseconds /= 10
        ms_str = has_float_format.group(1) % microseconds
        format = re.sub(float_format, ms_str[2:], format)
    return date.strftime(format)

print(datetime.datetime.now(), "%H:%M:%S.%.3f")
# '17:58:54.424'