1

I just started to play with wit/duckling. It is written in Clojure and I have no previous experience in Clojure. I need to parse a string like 2016-08-14T19:45:48.000+05:30 to a format like 1945hrs, Sunday, August 14th 2016. I searched on Internet and came across to lib clj-time. After struggling with it for a long time I came across this thread and thought that rfc822 is my cup of tea. So I used formatter rfc822 but it is giving me exception:

java.lang.IllegalArgumentException: Invalid format: "2016-08-16T00:00:00.000+05:30"

Here is my code:

(ns firstproj.core
  (:gen-class)
  (:require [duckling.core :as p])
  (:require [clj-time.format :as f]))

(defn -main
  "I don't do a whole lot."
  [x]
  (p/load! { :languages ["en"]})
  (def var_ (p/parse :en$core x [:time]))
  (def date_string "2016-08-14T19:45:48.000+05:30")
  (f/parse (f/formatters :rfc822) date_string))

So can anybody tell me what I am doing wrong here. Or any other way in Clojure to get my desired date-time format. As I am completely naive in Clojure, I request you to answer in detail, it will help me to understand this in a better way. Thank You.

Community
  • 1
  • 1
Saurabh Jain
  • 1,227
  • 1
  • 16
  • 28

2 Answers2

7

The clj-time library is a wrapper for Joda-Time. If you're using Java 8, you should prefer the built-in java.time library over Joda-Time, for reasons explained here. In Clojure, you can use the Clojure.Java-Time library, which wraps java.time. First, add it to your dependencies:

[clojure.java-time "0.2.1"]

Then you can use the offset-date-time and format functions in the java-time namespace:

(require '[java-time :as time])

(->> (time/offset-date-time "2016-08-14T19:45:48.000+05:30")
     (time/format "HHmm'hrs', EEEE, MMMM d y"))
;;=> "1945hrs, Sunday, August 14 2016"

As @Piotrek pointed out in his answer, Joda-Time doesn't seem to support the "th" in your original question. Judging from the DateTimeFormatter docs, neither does java.time.

Community
  • 1
  • 1
Sam Estep
  • 12,974
  • 2
  • 37
  • 75
3

Without actually checking which predefined formatter matches your date format you might just call:

(f/parse "2016-08-14T19:45:48.000+05:30")
;; => #object[org.joda.time.DateTime 0x1bd11b14 "2016-08-14T14:15:48.000Z"]

It will try all predefined formatters and return parsed value from the first one that succeeds.

Then to print in your custom format:

(require '[clj-time.core :as t])

(def my-time-zone (t/time-zone-for-offset 5 30))

(def my-formatter
  (f/formatter
    "HHmm'hrs', EEEE, MMMM dd yyyy"
    my-time-zone))

(f/unparse my-formatter some-date)
;; => "1945hrs, Sunday, August 14 2016"

Unfortunately to my knowledge JodaTime doesn't handle things like adding st, nd, rd, th to days.

Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49
  • I have updated my answer. By default dates are parsed and unparsed using UTC so the previous output was printed for UTC. – Piotrek Bzdyl Aug 14 '16 at 15:55