25

I would like a python datetime object to output (and use the result in django) like this:

Thu the 2nd at 4:30

But I find no way in python to output st, nd, rd, or th like I can with PHP datetime format with the S string (What they call "English Ordinal Suffix") (http://uk.php.net/manual/en/function.date.php).

Is there a built-in way to do this in django/python? strftime isn't good enough (http://docs.python.org/library/datetime.html#strftime-strptime-behavior).

Django has a filter which does what I want, but I want a function, not a filter, to do what I want. Either a django or python function will be fine.

CoatedMoose
  • 3,086
  • 1
  • 17
  • 34
Alexander Bird
  • 36,154
  • 41
  • 121
  • 156
  • If you don't find a ready-made solution, there are some good ones here you could convert: http://stackoverflow.com/questions/165713/how-do-i-provide-a-suffix-for-days-of-the-month – paxdiablo Sep 05 '10 at 00:16

5 Answers5

30

The django.utils.dateformat has a function format that takes two arguments, the first one being the date (a datetime.date [[or datetime.datetime]] instance, where datetime is the module in Python's standard library), the second one being the format string, and returns the resulting formatted string. The uppercase-S format item (if part of the format string, of course) is the one that expands to the proper one of 'st', 'nd', 'rd' or 'th', depending on the day-of-month of the date in question.

Alex Martelli
  • 811,175
  • 162
  • 1,198
  • 1,373
  • This could use more detail. For example you can use DateFormat(max_date).format("jS M, Y") which would format max_date as "1st May, 2019" – Scott Warren May 23 '19 at 07:20
20

dont know about built in but I used this...

def ord(n):
    return str(n)+("th" if 4<=n%100<=20 else {1:"st",2:"nd",3:"rd"}.get(n%10, "th"))

and:

def dtStylish(dt,f):
    return dt.strftime(f).replace("{th}", ord(dt.day))

dtStylish can be called as follows to get Thu the 2nd at 4:30. Use {th} where you want to put the day of the month ("%d" python format code)

dtStylish(datetime(2019, 5, 2, 16, 30), '%a the {th} at %I:%M')
Arvind Sridharan
  • 3,603
  • 3
  • 28
  • 52
Frosty Snowman
  • 325
  • 3
  • 5
  • 8
    @Arijoon That part covers the 'teens, which don't follow the same rules as everything else. If you remove it, you'll get `11st` or `13rd` when they should be `11th` and `13th`. – Status Oct 03 '15 at 21:58
9

You can do this simply by using the humanize library

from django.contrib.humanize.templatetags.humanize import ordinal

You can then just give ordinal any integer, ie

ordinal(2) will return 2nd

Adrian Krige
  • 91
  • 1
  • 1
5

I've just written a small function to solve the same problem within my own code:

def foo(myDate):
    date_suffix = ["th", "st", "nd", "rd"]

    if myDate % 10 in [1, 2, 3] and myDate not in [11, 12, 13]:
        return date_suffix[myDate % 10]
    else:
        return date_suffix[0]
Edster
  • 85
  • 2
  • 8
0

Following solution I got for above problem:

datetime.strptime(mydate, '%dnd %B %Y')
datetime.strptime(mydate, '%dst %B %Y')
datetime.strptime(mydate, '%dth %B %Y')
datetime.strptime(mydate, '%drd %B %Y')
Tiw
  • 5,078
  • 13
  • 24
  • 33
eegloo
  • 157
  • 1
  • 9
  • 1
    I am looking for a way to take a datetime object and convert it to a string with ordinals in it. This answer goes the opposite direction. – Alexander Bird Mar 04 '19 at 14:43