The strftime function is the prescribed way to format dates and times in Python (and other languages). It has limitations, such as forcing a leading zero on days of the month, 01-31, and on 12-hour clock hours, 01-12.
Edit I noticed that we were repeatedly writing expressions like these
d.strftime('%A, %B ') + str(d.day)
t.strftime("%I:%M").lstrip('0') + ('a' if t.hour < 12 else 'p')
and realized that there had to be a better way.
Here's a straightforward way to augment the directives: preprocess the format string, replacing new directives with their values, then let the underlying strftime implementation take care of the rest.
import re
_re_aux_format = re.compile("%([DiP])")
def strftime_aux(d, format):
"""
Augmented strftime that handles additional directives.
%D Day of the month as a decimal number [1,31] (no leading zero)
%i Hour (12-hour clock) as a decimal number [1,12] (no leading zero)
%P 'a' for AM, 'p' for PM
>>> import datetime
>>> d = datetime.datetime(2009, 4, 1, 9+12, 37)
>>> strftime_aux(d, '%A, %B %d, %I:%M %p')
'Wednesday, April 01, 09:37 PM'
>>> strftime_aux(d, '%A, %B %D, %i:%M%P')
'Wednesday, April 1, 9:37p'
"""
# Precompute the values of the augmented directives
directive_map = {
'D': str(d.day),
'i': '12' if d.hour in (0, 12) else str(d.hour % 12),
'P': 'a' if d.hour < 12 else 'p',
}
# Substitute those values into the format string
new_format = _re_aux_format.sub(
lambda match: directive_map.get( match.group(1), ''),
format)
# Let the stock implementation of strftime handle everything else
return d.strftime(new_format)
if __name__ == "__main__":
import doctest
doctest.testmod()





Comments