How can I format a datetime
object as a string with milliseconds?
To get a date string with milliseconds, use [:-3]
to trim the last three digits of %f
(microseconds):
>>> from datetime import datetime
>>> datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
'2022-09-24 10:18:32.926'
Or shorter:
>>> from datetime import datetime
>>> datetime.utcnow().strftime('%F %T.%f')[:-3]
'2022-09-24 10:18:32.926'
See the Python docs for more "%
" format codes and the strftime(3)
man page for the full list.
import datetime
instead of from datetime import datetime
, you'll have to use this: datetime.datetime.utcnow().strftime("%H:%M:%S.%f")
–
Lugworm (dt, micro) = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.') ; dt = "%s.%03d" % (dt, int(micro) / 1000) ; print dt
. I added this as an answer. –
Delisadelisle (dt, micro) = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f').split('.') ; dt = "%s.%03d" % (dt, round(int(micro) / 1000.0)) ; print dt
–
Hammonds %Y-%m-%d %H:%M:%S.%f
== %F %T.%f
–
Halftimbered %F %T
documented? I can't find it in the Python's page for datetime
. Is it deprecated? It works even in Python 3.10, though. I do see it in pages on POSIX datetime format codes. –
Merengue 2024-02-17 11/22/38
(slashes instead of colons!). Here is my code: timestamp = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
. Using .
or _
works, but not :
for some reason. Hah! –
Centralization With Python 3.6+, you can set isoformat
's timespec
:
>>> from datetime import datetime
>>> datetime.utcnow().isoformat(sep=' ', timespec='milliseconds')
'2019-05-10 09:08:53.155'
[:-3]
in the accepted answer, but you should know that it seemingly does the same >>> datetime.fromisoformat('2021-12-08 20:00:00.678900').isoformat(sep=' ', timespec='milliseconds')
leads to '2021-12-08 20:00:00.678'
. Is the truncation specified in ISO standard or is it just a bug? The implementation uses integer division: github.com/python/cpython/blob/… –
Hescock @Cabbi raised the issue that on some systems (Windows with Python 2.7), the microseconds format %f
may incorrectly give "0"
, so it's not portable to simply trim the last three characters. Such systems do not follow the behavior specified by the documentation:
Directive | Meaning | Example |
---|---|---|
%f | Microsecond as a decimal number, zero-padded to 6 digits. | 000000, 000001, …, 999999 |
The following code carefully formats a timestamp with milliseconds:
>>> 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'
To get the exact output that the OP wanted, we have to strip punctuation characters:
>>> from datetime import datetime
>>> (dt, micro) = datetime.utcnow().strftime('%Y%m%d%H%M%S.%f').split('.')
>>> "%s%03d" % (dt, int(micro) / 1000)
'20160226043839901'
Using strftime
:
>>> from datetime import datetime
>>> datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
'20220402055654344968'
[:-3]
to the end to drop the last 3 digits so that it is only displaying milliseconds. –
Himself Use [:-3]
to remove the 3 last characters since %f
is for microseconds:
>>> from datetime import datetime
>>> datetime.now().strftime('%Y/%m/%d %H:%M:%S.%f')[:-3]
'2013/12/04 16:50:03.141'
In python 3.6 and above using python f-strings:
from datetime import datetime, timezone
dt = datetime.now(timezone.utc)
print(f"{dt:%Y-%m-%d %H:%M:%S}.{dt.microsecond // 1000:03d}")
The code specific to format milliseconds is:
{dt.microsecond // 1000:03d}
The format string {:03d}
and microsecond to millisecond conversion // 1000
is from def _format_time
in https://github.com/python/cpython/blob/master/Lib/datetime.py that is used for datetime.datetime.isoformat().
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)
<<<<<< OUTPUT >>>>>>>
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
I assume you mean you're looking for something that is faster than datetime.datetime.strftime(), and are essentially stripping the non-alpha characters from a utc timestamp.
You're approach is marginally faster, and I think you can speed things up even more by slicing the string:
>>> 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
In Python 3.11 (maybe older version support it too) it can be done with isoformat(timespec='milliseconds')
From datetime.py
:
The optional argument timespec specifies the number of additional terms of the time to include. Valid options are 'auto', 'hours', 'minutes', 'seconds', 'milliseconds' and 'microseconds'.
>>> datetime.now().isoformat(timespec='milliseconds')
'2023-12-01T10:34:18.657'
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:] "
result
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:]
Use of translate() and slicing method run in same time
translate() presents the advantage to be usable in one line
Comparing the times on the basis of the first one:
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 * s[:4] + s[5:7] + s[8:10] + s[11:13] + s[14:16] + s[17:19] + s[20:]
I dealt with the same problem but in my case it was important that the millisecond was rounded and not truncated
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]
python -c "from datetime import datetime; print str(datetime.now())[:-3]"
2017-02-09 10:06:37.006
datetime
t = datetime.datetime.now()
ms = '%s.%i' % (t.strftime('%H:%M:%S'), t.microsecond/1000)
print(ms)
14:44:37.134
If you are prepared to store the time in a variable and do a little string manipulation, then you can actually do this without using the datetime module.
>>> _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 will round to out put the nearest millisecond, if you want more or less precision just change the number of decimal places
>>> 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
>>>
Tested in Python 2.7 and 3.7 (obviously you need to leave out the brackets when calling print in version 2.x).
The problem with datetime.utcnow()
and other such solutions is that they are slow.
More efficient solution may look like this one:
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
Where prec
would be 3
in your case (milliseconds).
The function works up to 9 decimal places (please note number 9
in the 2nd formatting string).
If you'd like to round the fractional part, I'd suggest building "%.9f"
dynamically with desired number of decimal places.
Field-width format specification
The UNIX date
command allows specifying %3
to reduce the precision to 3 digits:
$ date '+%Y-%m-%d %H:%M:%S.%3N'
2022-01-01 00:01:23.456
Here's a custom function that can do that in 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}")
Example usage:
>>> strftime_("%Y-%m-%d %H:%M:%S.%3f", datetime.now())
'2022-01-01 00:01:23.456'
NOTE: %%
is not supported.
© 2022 - 2024 — McMap. All rights reserved.
Instant.parse
can parse represenation created withstrftime('%Y-%m-%dT%H:%M:%S.%fZ')
– Harless