Feature Type

  • [X] Adding new functionality to pandas

  • [ ] Changing existing functionality in pandas

  • [ ] Removing existing functionality in pandas

Problem Description

Because of the restricted time range covered by Timestamp objects, I am building my code only using Period objects and indexes, as recommended by the doc. However, when using timestamps I could conveniently pass the object to a f-string with proper formatting strings. This doesn't work with Period objects.

Example:

import pandas as pd

t = pd.Timestamp('2262-04-11')
f"{t:%Y-%m}"
> '2262-04'

p = pd.Period('2262-04-11', 'H')
f"{p:%Y-%m}"
> TypeError: unsupported format string passed to Period.__format__

Feature Description

I think the easiest way to implement this would be:

class Period(...)
    ...
    def __format__(self, format_spec):
       return self.strftime(format_spec)

But I see that Period is not implemented in pure python, so I'm not sure how this impacts the implementation.

Alternative Solutions

The alternative is to cast the Periods to string before formatting the f-string, but that decouples the date formatting from the template itself.

Additional Context

Not super relevant to the issue, but in my context, the f-string are user-provided. My goal is to give that power to the user : one can choose how the dates are printed. The specific specific context where this bug was raised in my current code is when I generate a filename from a set of attributes, including some dates. I want the user to be able to choose between printing only the year or the year and month or anything else.

Comment From: venaturum

@aulemahal You can monkeypatch your idea in the meantime

import pandas as pd

def patch_Period_format():
    def __format__(self, fmt):
        # same implementation as datetime.datetime.__format__
        if not isinstance(fmt, str):
            raise TypeError("must be str, not %s" % type(fmt).__name__)
        if len(fmt) != 0:
            return self.strftime(fmt)
        return str(self)

    pd.Period.__format__ = __format__


patch_Period_format()
p = pd.Period('2262-04-11', 'H')
f"{p:%Y-%m}"
> '2262-04'

Comment From: smarie

~~relates to #51298~~ (EDIT: maybe not so much after all, sorry)

Comment From: jbrockmendel

PR would be welcome. Also since the OP we have implemented non-nanosecond support for datetime64 dtypes, which might be easier for your use case

Comment From: aulemahal

Indeed, my original problem was solved by storing dates as datetime64[ms]!