如何将datetime对象格式化为带有毫秒的字符串?


当前回答

@Cabbi提出了一个问题,在一些系统上(带有Python 2.7的Windows),微秒格式%f可能会错误地给出“0”,所以简单地修改最后三个字符是不可移植的。这样的系统不遵循文档中指定的行为:

Directive Meaning Example
%f Microsecond as a decimal number, zero-padded to 6 digits. 000000, 000001, …, 999999

下面的代码小心地以毫秒为单位格式化时间戳:

>>> from datetime import datetime
>>> (dt, micro) = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.')
>>> "%s.%03d" % (dt, int(micro) / 1000)
'2016-02-26 04:37:53.133'

为了得到OP想要的准确输出,我们必须去掉标点符号:

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

其他回答

datetime.utcnow()和其他此类解决方案的问题是它们很慢。

更有效的解决方案是这样的:

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

prec在你的例子中是3(毫秒)。

该函数最多工作到小数点后9位(请注意第二个格式化字符串中的数字9)。

如果您想四舍五入小数部分,我建议创建“%”。9f”动态地使用所需的小数点后数位。

使用strftime:

>>> from datetime import datetime
>>> datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
'20220402055654344968'

我假设您的意思是您正在寻找比datetime.datetime.strftime()更快的东西,并且实际上是从utc时间戳中剥离非alpha字符。

你的方法稍微快一点,我认为你可以通过切片字符串来加快速度:

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

如果您准备将时间存储在一个变量中并进行一些字符串操作,那么实际上无需使用datetime模块即可完成此操作。

>>> _now = time.time()
>>> print ("Time : %s.%s\n" % (time.strftime('%x %X',time.localtime(_now)),
... str('%.3f'%_now).split('.')[1])) # Rounds to nearest millisecond
Time : 05/02/21 01:16:58.676

>>> 

%。3f会四舍五入到最接近的毫秒,如果你想要更多或更少的精度,只需要改变小数点后的位数

>>> print ("Time : %s.%s\n" % (time.strftime('%x %X',time.localtime(_now)),
... str('%.1f'%_now).split('.')[1])) # Rounds to nearest tenth of a second
Time : 05/02/21 01:16:58.7

>>>

在Python 2.7和3.7中测试(显然,在版本2.x中调用print时需要省略括号)。

字段宽度格式规范

UNIX date命令允许指定%3将精度降低到3位:

$ date '+%Y-%m-%d %H:%M:%S.%3N'
2022-01-01 00:01:23.456

下面是一个自定义函数,它可以在Python中做到这一点:

from datetime import datetime

def strftime_(fmt: str, dt: datetime) -> str:
    tokens = fmt.split("%")
    tokens[1:] = [_format_token(dt, x) for x in tokens[1:]]
    return "".join(tokens)

def _format_token(dt: datetime, token: str) -> str:
    if len(token) == 0:
        return ""
    if token[0].isnumeric():
        width = int(token[0])
        s = dt.strftime(f"%{token[1]}")[:width]
        return f"{s}{token[2:]}"
    return dt.strftime(f"%{token}")

使用示例:

>>> strftime_("%Y-%m-%d %H:%M:%S.%3f", datetime.now())
'2022-01-01 00:01:23.456'

注:%%不支持。