将日期时间格式化为包含毫秒的字符串

Format a datetime into a string with milliseconds

提问人:Jurudocs 提问时间:9/29/2011 最后编辑:Mateen UlhaqJurudocs 更新时间:11/22/2023 访问量:792695

问:

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

python datetime 字符串格式化 毫秒

评论

1赞 cetver 9/29/2011
stackoverflow.com/questions/311627/......
4赞 agf 9/29/2011
请写一个描述您的问题的标题,并尽量保持您的问题清晰明了。
2赞 Jarek Przygódzki 3/8/2017
这里值得一提的是,额外的精度通常很好。例如,Java 可以解析使用Instant.parsestrftime('%Y-%m-%dT%H:%M:%S.%fZ')

答:

31赞 knitti 9/29/2011 #1

使用 strftime

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

评论

21赞 Mark Lakata 1/3/2014
仅供参考,这会将微秒打印为最后 6 位数字。添加到末尾以删除最后 3 位数字,以便它仅显示毫秒。[:-3]
9赞 cabbi 11/9/2015
微秒可以小于 6 位,因此 [:-3] 打印出错误的毫秒
15赞 ᐅdevrimbaris 3/4/2017
如果我们有时区怎么办?
1赞 Ena 5/10/2019
@ᐅdevrimbaris查看时区 Lorenzo的回答
2赞 Austin Marshall 9/29/2011 #2

我假设您的意思是您正在寻找比 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

评论

0赞 eyquem 9/29/2011
@oxtopus 干得好。就我个人而言,我不再使用 timeit 来简单地测量时间。奇怪的是,您的代码的时间比率不同:1 - 0.67 - 0.53 和我的:1 - 0.35 - 0.20 ,对于方法 strftime - replace - slicing
0赞 Austin Marshall 9/29/2011
也许与在测试的每次迭代中调用 str(datetime.datetime.utcnow()) 与设置一次有关?
1赞 eyquem 9/29/2011 #3
from datetime import datetime
from time import clock

t = datetime.utcnow()
print 't == %s    %s\n\n' % (t,type(t))

n = 100000

te = clock()
for i in xrange(1):
    t_stripped = t.strftime('%Y%m%d%H%M%S%f')
print clock()-te
print t_stripped," t.strftime('%Y%m%d%H%M%S%f')"

print

te = clock()
for i in xrange(1):
    t_stripped = str(t).replace('-','').replace(':','').replace('.','').replace(' ','')
print clock()-te
print t_stripped," str(t).replace('-','').replace(':','').replace('.','').replace(' ','')"

print

te = clock()
for i in xrange(n):
    t_stripped = str(t).translate(None,' -:.')
print clock()-te
print t_stripped," str(t).translate(None,' -:.')"

print

te = clock()
for i in xrange(n):
    s = str(t)
    t_stripped = s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:] 
print clock()-te
print t_stripped," s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:] "

结果

t == 2011-09-28 21:31:45.562000    <type 'datetime.datetime'>


3.33410112179
20110928212155046000  t.strftime('%Y%m%d%H%M%S%f')

1.17067364707
20110928212130453000 str(t).replace('-','').replace(':','').replace('.','').replace(' ','')

0.658806915404
20110928212130453000 str(t).translate(None,' -:.')

0.645189262881
20110928212130453000 s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:]

使用 translate() 和切片方法同时
运行 translate() 具有在一行中可用的优势

在第一个的基础上比较时间:

1.000 * t.strftime('%Y%m%d%H%M%S%f')

0.351 * str(t).replace('-','').replace(':','').replace('.','').replace(' ','')

0.198 * str(t).translate(None,' -:.')

0.194 * 秒[:4] + 秒[5:7] + 秒[8:10] + 秒[11:13] + 秒[14:16] + 秒[17:19] + s[20:]

评论

1赞 Austin Marshall 9/29/2011
好!在不牺牲性能的情况下,这确实更干净。str.translate() 在我的测试中实际上更快。
636赞 Jeremy Moritz 8/23/2013 #4

若要获取具有毫秒的日期字符串,请使用修剪(微秒)的最后三位数字:[:-3]%f

>>> from datetime import datetime
>>> datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
'2022-09-24 10:18:32.926'

或更短:

>>> from datetime import datetime
>>> datetime.utcnow().strftime('%F %T.%f')[:-3]
'2022-09-24 10:18:32.926'

有关更多 “” 格式代码,请参见 Python 文档,完整列表请参见 strftime(3) 手册页%

评论

9赞 Luc 9/16/2015
请注意,如果要使用 代替 ,则必须使用以下命令:import datetimefrom datetime import datetimedatetime.datetime.utcnow().strftime("%H:%M:%S.%f")
24赞 cabbi 11/9/2015
如果微秒为 0,则在 Windows 2.7 实现中不会打印出微秒,因此它会将秒:(
18赞 gens 10/2/2017
请注意,这会截断,而不是四舍五入到毫秒
3赞 Chris 11/21/2017
正如 gens 所提到的,这不会弄错吗,第一个掉落的数字是 >=5?。事实上,如果 usec 部分> 999500,那么你永远无法通过摆弄微秒部分来获得正确的时间
6赞 Technophile 7/2/2021
@gens时间方面,截断比四舍五入更可取。例如,07:59:59.999 应截断为 07:59:59 或 07:59,而不是四舍五入为 08:00:00 或 08:00,就像 07:59:59 应截断为 07:59 而不是四舍五入为 08:00。
11赞 N Fayçal 12/5/2013 #5

用于删除最后 3 个字符,因为是微秒:[:-3]%f

>>> from datetime import datetime
>>> datetime.now().strftime('%Y/%m/%d %H:%M:%S.%f')[:-3]
'2013/12/04 16:50:03.141'

评论

2赞 Technophile 7/2/2021
如其他答案中所述,如果微秒为 0,则“.123455”部分可能会打印为“.0”,导致最后 3 个字符被截断以吃掉低秒数字和“.0”。
1赞 omdaniel 7/29/2015 #6

我处理了同样的问题,但在我的情况下,毫秒是四舍五入而不是截断很重要

from datetime import datetime, timedelta

def strftime_ms(datetime_obj):
    y,m,d,H,M,S = datetime_obj.timetuple()[:6]
    ms = timedelta(microseconds = round(datetime_obj.microsecond/1000.0)*1000)
    ms_date = datetime(y,m,d,H,M,S) + ms
    return ms_date.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
35赞 Sam Watkins 2/26/2016 #7

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

命令 意义
%f 微秒作为十进制数,零填充为 6 位数字。 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'

评论

10赞 cabbi 3/8/2016
我实际上正在做的是:打印'%s.%03d'%(dt.strftime(“%Y-%m-%d %H:%M:%S”), int(dt.microsecond/1000))
3赞 caoanan 5/21/2018
同意@cabbi,没有必要用字符串和int来回转换
5赞 Waqas Ali 10/6/2016 #8
import datetime

# convert string into date time format.

str_date = '2016-10-06 15:14:54.322989'
d_date = datetime.datetime.strptime(str_date , '%Y-%m-%d %H:%M:%S.%f')
print(d_date)
print(type(d_date)) # check d_date type.


# convert date time to regular format.

reg_format_date = d_date.strftime("%d %B %Y %I:%M:%S %p")
print(reg_format_date)

# some other date formats.
reg_format_date = d_date.strftime("%Y-%m-%d %I:%M:%S %p")
print(reg_format_date)
reg_format_date = d_date.strftime("%Y-%m-%d %H:%M:%S")
print(reg_format_date)

<<<<<<输出>>>>>>>

2016-10-06 15:14:54.322989    
<class 'datetime.datetime'>    
06 October 2016 03:14:54 PM    
2016-10-06 03:14:54 PM    
2016-10-06 15:14:54
1赞 arntg 2/10/2017 #9
python -c "from datetime import datetime; print str(datetime.now())[:-3]"
2017-02-09 10:06:37.006
1赞 Hunaphu 3/5/2019 #10
datetime
t = datetime.datetime.now()
ms = '%s.%i' % (t.strftime('%H:%M:%S'), t.microsecond/1000)
print(ms)
14:44:37.134
159赞 Lorenzo 5/10/2019 #11

在 Python 3.6+ 中,您可以设置 isoformat 的:timespec

>>> from datetime import datetime
>>> datetime.utcnow().isoformat(sep=' ', timespec='milliseconds')
'2019-05-10 09:08:53.155'

评论

2赞 Ena 5/10/2019
对时区也很有用: date = datetime(2019,5,10) date_with_tz = pytz.timezone('Europe/Rome').localize(date) date_with_tz.isoformat(sep='T', timespec='milliseconds') 输出: '2019-05-10T00:00:00.000+02:00'
1赞 Wolf 12/9/2021
这看起来比公认的答案更干净,但你应该知道它似乎也会导致 .截断是在 ISO 标准中指定的还是只是一个错误?该实现使用整数除法:github.com/python/cpython/blob/...[:-3]>>> datetime.fromisoformat('2021-12-08 20:00:00.678900').isoformat(sep=' ', timespec='milliseconds')'2021-12-08 20:00:00.678'
0赞 Jimson James 12/4/2022
根据维基百科 (en.wikipedia.org/wiki/ISO_8601#cite_note-37),“ISO 8601 中不允许使用空格等其他字符分隔日期和时间部分,但在其配置文件 RFC 3339 中允许”,因此最好添加类似“T”之类的东西作为分隔符,以及“如果时间是 UTC,请直接在时间后添加 Z,没有空格”(摘自维基百科)。
0赞 mato 8/7/2019 #12

其他此类解决方案的问题在于它们速度很慢。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

在您的案例中的位置(毫秒)。prec3

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

如果你想对小数部分进行四舍五入,我建议使用所需的小数位数进行动态构建。"%.9f"

4赞 user1004488 10/2/2020 #13

在使用 python f-strings 的 python 3.6 及更高版本中:

from datetime import datetime, timezone

dt = datetime.now(timezone.utc)

print(f"{dt:%Y-%m-%d %H:%M:%S}.{dt.microsecond // 1000:03d}")

特定于格式化毫秒的代码为:

{dt.microsecond // 1000:03d}

格式字符串和微秒到毫秒的转换来自用于 datetime.datetime.isoformat()in https://github.com/python/cpython/blob/master/Lib/datetime.py{:03d}// 1000def _format_time

1赞 Mike T. 5/2/2021 #14

如果您准备将时间存储在变量中并执行一些字符串操作,那么您实际上可以在不使用 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 时需要省略括号)。

0赞 Mateen Ulhaq 4/2/2022 #15

字段宽度格式规范

UNIX 命令允许指定将精度降低到 3 位:date%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'

注意:不支持。%%