· clojure

Clojure: clj-time - Formatting a date / timestamp with day suffixes e.g. 1st, 2nd, 3rd

I’ve been using the clj-time library recently - a Clojure wrapper around Joda Time - and one thing I wanted to do is format a date with day suffixes e.g. 1st, 2nd, 3rd.

I started with the following timestamp:

1309368600000

The first step was to convert that into a DateTime object like so:

user> (require '[clj-time.coerce :as c])
user> (c/from-long 1309368600000)
#<DateTime 2011-06-29T17:30:00.000Z>

I wanted to output that date in the following format:

29th June 2011

We can get quite close by using a custom time formatter:

user> (require '[clj-time.format :as f])
nil
user> (f/unparse (f/formatter "d MMMM yyyy") (c/from-long 1309368600000))
"29 June 2011"

Unfortunately I couldn’t find anywhere in the documentation explaining how to get the elusive 'th' or 'st' to print. I was hoping for something similar to PHP date formatting:

2014 04 26 08 38 39

Eventually I came across a Stack Overflow post about Joda Time suggesting that you can’t actually format a day in the way I was hoping to.

So I now have the following function to do it for me:

(defn day-suffix [day]
  (let [stripped-day (if (< day 20) day (mod day 10))]
    (cond (= stripped-day 1) "st"
          (= stripped-day 2) "nd"
          (= stripped-day 3) "rd"
          :else "th")))

and the code to get the date in my favoured format looks like this:

user> (def my-time (c/from-long 1309368600000))
#'user/my-time
user> (def day (read-string (f/unparse (f/formatter "d") my-time)))
#'user/day
user> (str day (day-suffix day) " " (f/unparse (f/formatter "MMMM yyyy") my-time))
"29th June 2011"

I’m assuming there’s a better way but what is it?!

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket