139

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'

Yarin
  • 173,523
  • 149
  • 402
  • 512
  • 1
    Does this answer your question? [Python strftime - date without leading 0?](https://stackoverflow.com/questions/904928/python-strftime-date-without-leading-0) – SuperStormer Oct 12 '22 at 02:40

9 Answers9

260

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”

ChrisFreeman
  • 5,831
  • 4
  • 20
  • 32
  • 68
    Great answer, but Linux only. Won't work on Windows. http://stackoverflow.com/questions/10807164/python-time-formatting-different-in-windows – ExactaBox Jul 07 '15 at 18:13
  • 5
    Why does this work? I can't find a reference to this in the docs for `date.__format__` or `time.strftime`, https://docs.python.org/3/library/datetime.html#datetime.date.__format__, and https://docs.python.org/3.8/library/time.html#time.strftime respectively – Amin Shah Gilani Sep 30 '20 at 17:35
  • 2
    @Amin Shah Gilani, this is a Linux derived alternative, I’ve updated the post to link to this implementation specific feature’s origin. – ChrisFreeman May 29 '21 at 01:13
  • see below for windows solution – citynorman Feb 26 '22 at 14:38
115

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.

senderle
  • 145,869
  • 36
  • 209
  • 233
  • 2
    It has been around since python 2.6. (It's not _that_ new.) – senderle Mar 02 '12 at 00:44
  • 3
    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 :) – Jens Aug 01 '13 at 18:59
  • 2
    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. – Dana Cartwright Apr 04 '14 at 14:45
  • Note that this technique uses strftime, which will fail on dates prior to 1900. If you have old dates, you'll regret this. – mlissner Apr 06 '16 at 17:57
  • @mlissner, "this technique" => "the last technique" -- the first two don't use `strftime`. – senderle Apr 06 '16 at 23:21
  • @senderle Good point. It's surprising through, since strftime itself is not in sight. – mlissner Apr 06 '16 at 23:26
  • @mlissner, yes, I can see how that might be surprising. The `datetime` object's `__format__` method is basically an alias of [datetime.strftime](https://docs.python.org/2/library/datetime.html#datetime.datetime.__format__). So that's two layers of implicit behavior; the implicit call to `datetime.__format__` and the fact that `__format__` is an alias in this case. This might be one of those "practicality beats purity" moments. – senderle Apr 07 '16 at 01:53
  • 1
    fak! I just realized where I didn't point d to another object, I just passed it as a positional arg. – JacobIRR Jul 27 '18 at 18:41
94

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", " ")
Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 1
    Sven- Because I want to look like Facebook. Thanks! – Yarin Mar 01 '12 at 23:55
  • This is useful. I needed to create URLs with non-padded days, and had to string 3 of these together: dt.strftime("%B_")+dt.strftime("%d").lstrip("0")+dt.strftim\ e(",_%Y") – philshem Mar 27 '14 at 20:35
  • 4
    Very few people use zero-padded hours in North America when writing the time by hand. – Eric Walker Apr 24 '14 at 00:11
  • 3
    Won't this still zero pad the day of the month? – Judge Maygarden Sep 24 '14 at 14:32
  • 1
    @JudgeMaygarden: That's why the solution does `.lstrip("0")` to get rid of the leading zero. – Sven Marnach Sep 25 '14 at 21:34
  • This is the only answer that works as advertised on Windows to get a naturalized time output, but I wish there was a better way. – Adam Starrh Jun 17 '16 at 18:36
  • Some tools, e.g. AWS CloudWatch Logs, do not work well with non-zero-padded timestamps. – thinkski Dec 06 '16 at 17:12
  • Just adding a note that "%e" instead of "%d" for the day of the month will space pad the single-digit days. That is not generally useful so it makes more sense to do the .replace(" 0"," ") approach with "%d". – Kevin Buchs Sep 04 '17 at 15:02
  • 1
    Why I want to remove pad zeroes? Because this is wrong by [RFC 2822](http://www.faqs.org/rfcs/rfc2822.html), for example in podcast feed. – Vitaly Zdanevich Jul 01 '19 at 11:56
86

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
    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. – sagneta Mar 14 '17 at 16:49
  • 4
    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. – Keith Feb 13 '18 at 23:24
  • 1
    Why does this answer has so less upvotes? It's better than all the better-voted. – GuiTaek Sep 21 '21 at 17:44
22

Good answer from Chris Freeman on Linux.

On windows, it's:

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

Thought that might help.

user3685285
  • 6,066
  • 13
  • 54
  • 95
2

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.

Dendi Handian
  • 348
  • 2
  • 12
  • 1
    The question is for strftime(), to print the date as string. Not to parse from string using strptime(). – Siddu Apr 09 '23 at 08:58
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.

Timothy C. Quinn
  • 3,739
  • 1
  • 35
  • 47
  • 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. – R.M. Nov 17 '22 at 00:20
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.

Rob Cranfill
  • 2,306
  • 1
  • 18
  • 15
  • 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 – Ankur Tripathi Nov 28 '20 at 02:29
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

Lorenzo Bassetti
  • 795
  • 10
  • 15