我目前正在记录一些东西,并使用自己的格式化程序以及一个自定义的formatTime()
函数:
def formatTime(self, _record, _datefmt):
t = datetime.datetime.now()
return t.strftime('%Y-%m-%d %H:%M:%S.%f')
我的问题是微秒,%f
,有六个数字。是否有办法输出较少的数字,比如微秒的前三个数字?
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')
head = s[:-7] # everything up to the '.'
tail = s[-7:] # the '.' and the 6 digits after it
f = float(tail)
temp = "{:.03f}".format(f) # for Python 2.x: temp = "%.3f" % f
new_tail = temp[1:] # temp[0] is always '0'; get rid of it
return head + new_tail
从Python 3.6版本开始,该语言已经内置了此功能:
def format_time():
t = datetime.datetime.now()
s = t.isoformat(timespec='milliseconds')
return s
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
),这会对我将这些时间戳馈送到解析器中造成问题。这种方法没有这个问题。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]
您可以从微秒中减去当前日期和时间。
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
编辑:正如下面评论中一些人指出的那样,该解决方案(以及上面的一个解决方案)在微秒值达到999500时会引入问题,因为999.5会舍入为1000(溢出)。
除了重新实现strftime以支持我们想要的格式(由于舍入引起的潜在溢出需要向上传递到秒,然后是分钟等等),最简单的方法是像接受的答案中所述,将其截断到前3位,或使用以下内容:
'{:03}'.format(int(999999/1000))
-- 保留原始答案如下 --
在我的情况下,我正在尝试将日期戳格式化为毫秒格式化为“ddd”。 我最终使用的解决方法是使用datetime
对象的microsecond
属性,将其除以1000.0,如果必要则用零填充,并通过格式进行四舍五入。它看起来像这样:
'{:03.0f}'.format(datetime.now().microsecond / 1000.0)
# Produces: '033', '499', etc.
'{:03}'.format(datetime.now().microsecond // 1000)
- Nick Matteoimport 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())
steveha 已经说过截断。那会将你向下舍入。但如果你想要四舍五入到最接近的数字,一般来说,舍入数字的方法是在截断之前,在小数位的位置上加上5。所以例如,要将12.3456四舍五入到小数点后3位,加上0.0005;这给出了12.3461,然后你将其截断为小数点后3个字符,得到了12.346。
问题是,如何正确地在下一位小数后加5。所以你不能只考虑微秒,如果你在除夕夜午夜前刚好超过0.9995秒时进行四舍五入,进位可能会一直到年份!
但你可以使用时间差(timedelta)。然后时间计算是正确的,你只需截断即可获得正确舍入的值。
要将秒数四舍五入到小数点后3位,你希望添加0.0005秒=500微秒。这里有3个例子:首先,将0.1234秒四舍五入为0.123,然后将0.1235秒四舍五入为0.124,然后当你应该亲吻某人祝他们新年快乐时,进位会一直传递到全年而你却在做Python:
>>> r = datetime.timedelta(microseconds=500)
>>> t = datetime.datetime(2023,1,2,3,45,6,123456)
>>> (t+r).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
'2023-01-02 03:45:06.123'
>>> t = datetime.datetime(2023,1,2,3,45,6,123556)
>>> (t+r).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
'2023-01-02 03:45:06.124'
>>> t = datetime.datetime(2023,12,31,23,59,59,999500)
>>> (t+r).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
'2024-01-01 00:00:00.000'
这种方法允许灵活的精度,并且如果您指定了过大的精度,它将消耗整个微秒值。
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))
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
模块的精度是基于字符串的。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小时制
谢谢。
f
变量)在小数点前添加了前导0(例如:0.367
),这被附加为字符串。秒数区域中的前导0是出错的起点。 - NuclearPeonf
之后,您可以通过以下方式进行修复:if f >= 1.0: return (t + datetime.timedelta(milliseconds=1)).strftime('%Y-%m-%d %H:%M:%S.000')
(否则继续如之前所述)。 - Nick Matteologging.basicConfig
中的datefmt
无效。 - Att Righ