155

Is there a format for printing Python datetimes that won't use zero-padding on dates and times?

Format I'm using now:

mydatetime.strftime('%m/%d/%Y %I:%M%p')

Result: 02/29/2012 05:03PM
Desired: 2/29/2012 5:03PM

What format would represent the month as '2' instead of '02', and time as '5:03PM' instead of '05:03PM'

1

12 Answers 12

277

The other alternate to avoid the "all or none" leading zero aspect above is to place a minus in front of the field type:

mydatetime.strftime('%-m/%d/%Y %-I:%M%p')

Then this: '4/10/2015 03:00AM'

Becomes: '4/10/2015 3:00AM'

You can optionally place a minus in front of the day if desired.

Edit: The minus feature derives from the GNU C library (“glibc”) as mentioned in the Linux strftime manpage under “Glibc notes”

Sign up to request clarification or add additional context in comments.

4 Comments

Great answer, but Linux only. Won't work on Windows. stackoverflow.com/questions/10807164/…
Why does this work? I can't find a reference to this in the docs for date.__format__ or time.strftime, docs.python.org/3/library/…, and docs.python.org/3.8/library/time.html#time.strftime respectively
@Amin Shah Gilani, this is a Linux derived alternative, I’ve updated the post to link to this implementation specific feature’s origin.
see below for windows solution
123

The new string formatting system provides an alternative to strftime. It's quite readable -- indeed, it might be preferable to strftime on that account. Not to mention the fact that it doesn't zero-pad:

>>> '{d.month}/{d.day}/{d.year}'.format(d=datetime.datetime.now())
'3/1/2012'

Since you probably want zero padding in the minute field, you could do this:

>>> '{d.month}/{d.day}/{d.year} {d.hour}:{d.minute:02}'.format(d=now)
'3/1/2012 20:00'

If you want "regular" time instead of "military" time, you can still use the standard strftime specifiers as well. Conveniently, for our purposes, strftime does provide a code for the 12-hour time padded with a blank instead of a leading zero:

'{d.month}/{d.day}/{d.year} {d:%l}:{d.minute:02}{d:%p}'.format(d=now)
'4/4/2014  6:00PM'

This becomes somewhat less readable, alas. And as @mlissner points out, strftime will fail on some (all?) platforms for dates before 1900.

8 Comments

It has been around since python 2.6. (It's not that new.)
To spell out the month, for example, you can use the following: "{0.day} {0:%B %Y}".format(d) which would give you '2 August 2013' as the day of this comment :)
This is interesting, but it doesn't actually answer OP, because he wants AM/PM hours. I'm not actually going to downvote it, but the accepted answer is actually right if you are trying to get "American" date/time formatting in python.
Note that this technique uses strftime, which will fail on dates prior to 1900. If you have old dates, you'll regret this.
fak! I just realized where I didn't point d to another object, I just passed it as a positional arg.
|
95

The formatting options available with datetime.strftime() will all zero-pad. You could of course roll you own formatting function, but the easiest solution in this case might be to post-process the result of datetime.strftime():

s = mydatetime.strftime('%m/%d/%Y %I:%M%p').lstrip("0").replace(" 0", " ")

9 Comments

Sven- Because I want to look like Facebook. Thanks!
Very few people use zero-padded hours in North America when writing the time by hand.
Won't this still zero pad the day of the month?
@JudgeMaygarden: That's why the solution does .lstrip("0") to get rid of the leading zero.
Why I want to remove pad zeroes? Because this is wrong by RFC 2822, for example in podcast feed.
|
95

Accepted answer not a proper solution (IMHO) The proper documented methods:

In Linux "#" is replaced by "-":

%-d, %-H, %-I, %-j, %-m, %-M, %-S, %-U, %-w, %-W, %-y, %-Y

In Windows "-" is replaced by "#":

%#d, %#H, %#I, %#j, %#m, %#M, %#S, %#U, %#w, %#W, %#y, %#Y

#Linux
mydatetime.strftime('%-m/%d/%Y %-I:%M%p')

# Windows
mydatetime.strftime('%#m/%d/%Y %#I:%M%p')

Source: https://msdn.microsoft.com/en-us/library/fe06s4ak.aspx

As stated by Sagneta: The # hash trick on Windows is only available to native python executable. this will not work for cygwin-based python implementations.

3 Comments

This is correct. Due note however that the # hash trick on Windows is only available to native python executables. In other words, this will not work for cygwin-based python implementations.
Wow this great to know but I'm horrified of the consequence. I'm testing date formatting returned from a Database and I need to pass in the expected formatting for each test and this adds tons of complexity.
Seems to be incorrect in 2024: "-" and "#" both give me a "bad directive" error. Context: tested from a Windows 10 machine with python 3.12.1 and using a virtual environment installed to a local .venv folder in the project via Visual Studio Code. I'm trying to go in the opposite direction: use strptime to convert a string to a datetime.
24

Good answer from Chris Freeman on Linux.

On windows, it's:

mydate.strftime('%#m/%#d/%Y')

Comments

2

another option:

yourdatetime.strftime('%-m/%-d/%Y %-I:%M%p')

Comments

1

As mentioned by several others, to ignore leading zero on windows, you must use %#d instead of %-d.

For those who like to write clean cross platform python code, without seeing platform switches in business logic, here is a Python3 helper that enables you to have one format string for both Windows, Linux and Others (tested Linux, Windows and FreeBSD):

import os
from datetime import datetime

def dateToStr(d: datetime, fmt: str) -> str:
    return d.strftime(fmt.replace('%-', '%#') if os.name == 'nt' else fmt)

dateToStr(datetime.now(), '%-m/%-d/%-Y')

On a side note, this is another one of those Whaaaaaaaat? features in Python. I don't understand why they did not create a standard format set for all platforms and add an optional 'use_native' flag to use native platform features. Guess it was an early design decision that must be kept for legacy support.

1 Comment

This is the best solution. It's the only answer that still lets you use strftime(), and combine padded and non padded elements, instead of either having all of them or none of them.
0

"%l" (that's a lower-case L) works for the hour (instead of "%I"). I only know this from another answer here

Python strftime - date without leading 0?

but unfortunately they don't have the code for the other elements of a date/time.

1 Comment

pd.to_datetime(dt['Time'], format= '%l:%M:%S', infer_datetime_format=True) After try %l still not working for me Error:- File "pandas_libs\tslibs\conversion.pyx", line 399, in pandas._libs.tslibs.conversion.convert_datetime_to_tsobject File "pandas_libs\tslibs\np_datetime.pyx", line 117, in pandas._libs.tslibs.np_datetime.check_dts_bounds pandas._libs.tslibs.np_datetime.OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 1-01-01 09:15:59
0

I use this:

D = str(datetime.now().day)
MM = str(datetime.now().month)
YYYY = str(datetime.now().year)

This, today, will return: 2, 12, 2021

1 Comment

Doesn't work properly for hours at midnight and after noon.
0

In the official docs formating section:

  1. When used with the strptime() method, the leading zero is optional for formats %d, %m, %H, %I, %M, %S, %J, %U, %W, and %V. Format %y does require a leading zero.

So, using %d to parse day in number will automatically parse both 07 & 7 for example.

1 Comment

The question is for strftime(), to print the date as string. Not to parse from string using strptime().
0

I just came across this for the first time, since I previously did most development work on linux exclusively. Here is my solution for an easy cross-platform approach on Python 3.8+

from typing import AnyStr

import os

def unistrfmt(fmt: AnyStr) -> AnyStr:
    return fmt.replace(('%#', '%-')[os.name == 'nt'], ('%-', '%#')[os.name == 'nt'])

# Examples:

from datetime import date
date.today().strftime(unistrfmt("%Y.%m.%-d"))
# '2024.02.1'
os.name
#'nt'
unistrfmt("%Y.%m.%-d")
# '%Y.%m.%#d'
unistrfmt("%Y.%m.%#d")
# '%Y.%m.%#d'

Comments

-1

Add a # in front of the format descriptor to remove zero padding:

mydatetime.strftime('%#m/%d/%Y %#I:%M%p')

1 Comment

This is already mentioned in other answers: stackoverflow.com/a/42709606/2745495

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.