Skip to content
Advertisement

How do I format a date and also pad it with spaces?

Formatting appears to work differently if the object you’re formatting is a date.

today = "aaa"
print(f'{today:>10}')

returns

       aaa

i.e. it has the padding.

If I now do this:

today = datetime.date.today()
print(f'{today:>10}')

then the response is

>10

Which is obviously not what I want. I’ve tried various other combinations where I put in the date format as well, but all it does is draw the date out and then also add in ‘>10’ also.

How do I format a date with padding?

Advertisement

Answer

Python’s scheme for formatting via f-strings (and the .format method of strings) allows the inserted data to override how the format specification works, using the __format__ magic method:

>>> class Example:
...     def __format__(self, template):
...         return f'{template} formatting of {self.__class__.__name__} instance'
... 
>>> f'{Example():test}'
'test formatting of Example instance'

datetime.date does this, so that time.strftime is used to do the formatting (after some manipulation, e.g. inserting a proxy time for dates and vice-versa):

>>> help(today.__format__)
Help on built-in function __format__:

__format__(...) method of datetime.date instance
    Formats self with strftime.

This means that codes like %Y etc. can be used, but field width specifiers (like >10) are not supported. The format string >10 doesn’t contain any placeholders for any components of the date (or time), so you just get a literal >10 back.

Fortunately, it is trivial to work around this. Simply coerce the date to string, and pad the string:

>>> f'{str(today):>20}'
'          2022-06-13'

Or better yet, use the built-in syntax for such coercion:

>>> f'{today!s:>20}' # !s for str(), !r for repr()
'          2022-06-13'

If you want to use the strftime formatting as well, do the formatting in two steps:

>>> formatted = f'{today:%B %d, %Y}'
>>> f'{formatted:>20}'
'       June 13, 2022'

Note that it does not work to nest format specifiers:

>>> # the {{ is interpreted as an escaped literal {
>>> f'{{today:%B %d, %Y}:>20}' 
  File "<stdin>", line 1
SyntaxError: f-string: single '}' is not allowed
>>> # the inner {} looks like a dict, but %B isn't an identifier
>>> f'{ {today:%B %d, %Y}:>20}'
  File "<fstring>", line 1
    ( {today:%B %d, %Y})
             ^
SyntaxError: invalid syntax

However, f-strings themselves can be nested (this is obviously not very elegant and will not scale well):

>>> # instead of trying to format the result from another placeholder,
>>> # we reformat an entire separately-formatted string:
>>> f'{f"{today:%B %d, %Y}":>20}'
'       June 13, 2022'
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement