The simplest way would be to use slicing to just chop off the last three digits of the microseconds:

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

I strongly recommend just chopping. I once wrote some logging code that rounded the timestamps rather than chopping, and I found it actually kind of confusing when the rounding changed the last digit. There was timed code that stopped running at a certain timestamp yet there were log events with that timestamp due to the rounding. Simpler and more predictable to just chop.

If you want to actually round the number rather than just chopping, it's a little more work but not horrible:

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

Obviously you can simplify the above with fewer variables; I just wanted it to be very easy to follow.

Answer from steveha on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › python › how-to-use-strptime-with-milliseconds-in-python
How to use strptime with milliseconds in Python - GeeksforGeeks
July 23, 2025 - from datetime import datetime s = "15/06/2021 13:30:15.120" format = "%d/%m/%Y %H:%M:%S.%f" dt_obj = datetime.strptime(s, format) print(dt_obj) ... Use %f when you want to include milliseconds or microseconds in your datetime string.
🌐
Python documentation
docs.python.org › 3 › library › datetime.html
datetime — Basic date and time types — Python 3.14.3 documentation
'minutes': Include hour and minute in HH:MM format. 'seconds': Include hour, minute, and second in HH:MM:SS format. 'milliseconds': Include full time, but truncate fractional second part to milliseconds.
🌐
GitHub
github.com › selectel › tempo › issues › 1
milliseconds in strptime and strftime · Issue #1 · selectel/tempo
June 25, 2012 - For example: (tempo_dev@garry-... line 115) Also, there is no way to set right format, because strptime and strftime do not support milliseconds....
Author   2garryn
🌐
TutorialsPoint
tutorialspoint.com › how-to-use-strptime-with-milliseconds-in-python
How to use strptime with milliseconds in Python
October 13, 2023 - import time struct_time = time.strptime("30 Nov 00", "%d %b %y") print("Returned object:", struct_time) When we run above program, it produces following result − · Returned object: time.struct_time(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
🌐
YouTube
youtube.com › codelearn
python time format milliseconds 3 digits - YouTube
Download this code from https://codegive.com When working with time in Python, you may encounter situations where you need to work with milliseconds and repr...
Published   December 14, 2023
Views   256
Find elsewhere
🌐
Esri Community
community.esri.com › t5 › python-questions › milliseconds-with-strftime › td-p › 73258
Solved: Milliseconds with strftime - Esri Community
December 10, 2021 - I need to return time to the millisecond;Python strftime reference provides the %f format place holder, but when I use it in Python 3.x it fails. This works: from time import strftime site = 'FP 20180822' for i in range(1,10): theTime = strftime("%H%M%S") newTime = '{} {}'.format(site,theT...
🌐
Splunk
answers.splunk.com › t5 › - › - › td-p › 12497
What is the strptime-style %-variable that TIME_FORMAT would use for subseconds?
January 16, 2023 - To add detail to gkapanthy's answer, the %3N means you have 3 digits of subseconds (milliseconds) while %6N is microseconds. You could use %9N for nanoseconds (dtrace uses this granularity, for example). We used system strptime at one point, nowadays we have our own implementation which supports ...
🌐
Delft Stack
delftstack.com › home › howto › python › python datetime milliseconds
How to Convert DateTime to String With Milliseconds in Python | Delft Stack
February 2, 2024 - This method is faster than the above methods, but we could specify the string format. We can also simply remove the last three digits from the string to get the final result in milliseconds.
🌐
APIdock
apidock.com › ruby › datetime › strftime
DateTime#strftime - APIdock
20 in 2009) %y - year % 100 (00..99) %m - Month of the year, zero-padded (01..12) %_m blank-padded ( 1..12) %-m no-padded (1..12) %B - The full month name (``January'') %^B uppercased (``JANUARY'') %b - The abbreviated month name (``Jan'') %^b uppercased (``JAN'') %h - Equivalent to %b %d - Day of the month, zero-padded (01..31) %-d no-padded (1..31) %e - Day of the month, blank-padded ( 1..31) %j - Day of the year (001..366) Time (Hour, Minute, Second, Subsecond): %H - Hour of the day, 24-hour clock, zero-padded (00..23) %k - Hour of the day, 24-hour clock, blank-padded ( 0..23) %I - Hour of
🌐
CopyProgramming
copyprogramming.com › howto › strptime-format-and-saving-the-milliseconds
Python: Saving Milliseconds While Formatting Time Using Strptime
April 18, 2023 - My time tag is saved in the format of HH:MM:SS.f and contains 5 digits for milliseconds. However, I'm facing an issue as strptime's %f format only accepts 3 digits.
🌐
CopyProgramming
copyprogramming.com › howto › format-a-datetime-into-a-string-with-milliseconds
Python: Convert datetime with milliseconds to string format
May 10, 2023 - The final result in milliseconds can be obtained by removing the last three digits from the string. from datetime import datetime t = datetime.now() date_s = str(t)[:-3] print(date_s)
🌐
Microsoft Learn
learn.microsoft.com › en-us › answers › questions › 1883867 › assistance-with-formatting-and-parsing-millisecond
Assistance with Formatting and Parsing Milliseconds in Visual Studio - Microsoft Q&A
August 18, 2024 - Since I don't know the type of Milliseconds and this.spinner_MILLISECONDS.Digits, I tested it in the following way. DateTime Time { get; set; } public MainWindow() { InitializeComponent(); string Hours = "2"; string Minutes = "2"; string Seconds = "2"; string Milliseconds = "1"; Milliseconds = NumberFormatter(3 - Milliseconds.Length, Milliseconds); Seconds = NumberFormatter(2 - Seconds.Length, Seconds); Minutes = NumberFormatter(2 - Minutes.Length, Minutes); Hours = NumberFormatter(2 - Hours.Length, Hours); this.Time = DateTime.Parse(Hours + ":" +Minutes + ":" +Seconds + "." +Milliseconds); MessageBox.Show(this.Time.Millisecond.ToString()); }
Top answer
1 of 2
4

Function strptime() in not part of any Standard C library. It is well defined in *nix systems. It commonly uses a pointer to struct tm.

struct tm is defined to have at least 9 members. It may have more. There is no specified member corresponding to time units finer than seconds.

Sometimes struct tm has a member for milliseconds, microseconds, etc. Yet that is implementation dependent.

Referenced strptime() simply does not have a specifier for sub-seconds. Code needs to handle such optional members in some other fashion.


struct tm woes

Without "%Z", strptime() forms the struct tm without adjusting .tm_isdst. In general, strptime() does not certainly assign all struct tm members.

Initialize struct tm prior to the strptime().

struct tm time_stamp = { 0 };

Sample validation:

// Return error flag
bool testit(struct tm *t, int *ms, const char *date) {
  memset(t, 0, sizeof *t);

  const char *s = strptime(date, "%Y/%m/%dT%H:%M:%S", &t);
  if (s == NULL) {
    return true;
  }

  int n = 0;
  sscanf(s, ".%3dZ%n", ms, &n);
  return (n < 5 || s[5] != 0);
}

For the pedantic: detect rump milliseconds as exactly as 3 digits.

unsigned char *uc = (unsigned char *)s; 
if (uc[0] != '.' || !isdigit(uc[1]) || !isdigit(uc[2])
    || !isdigit(uc[3]) || uc[4] != 'Z' || uc[5]) {
  return true;
}
uc[4] = 0;
*ms = atoi(s + 1);
return false;
2 of 2
3

A workaround way is to design your own struct tm which contains a member for milliseconds:

struct tm2 {
  struct tm tm;
  long ms;
};

Then you have to parse the milliseconds part manually (I haved updated the code according to @Fe2O3's comment):

  const char *date = "2023/10/04T11:41:03.553Z";
  struct tm2 tm2;

  char *peroid = strptime(date, "%Y/%m/%dT%H:%M:%S", &tm2.tm);
  if (peroid == NULL) {
    printf("error format!\n");
  } else if (*peroid == '.') {
    char *endstr;
    tm2.ms = strtol(peroid + 1, &endstr, 10);
    if (*endstr != 'Z') {
      printf("error format!\n");
    }
  } else {
    printf("error format!\n");
  }

To make the code more robust, you can adjust error checking code.