[2014-11-10] Challenge #188 [Easy] yyyy-mm-ddThe challenge is to covert dates in various formats into ISO8601 format. | (ns daily.easy-188 (:require [dommy.core :as dommy :refer-macros [sel1]] [reagent.core :as reagent :refer [atom]] [ajax.core :refer [GET POST]] [clojure.string :as string])) |
SolutionAuxiliary Functions | |
Converts a two digit year string into a four digit year string. The valid two digit years are between 1950 and 2049. This means numbers between 00 and 49 get 20 preappended and numbers between 50 and 99 get 19. | (defn convert-year [two-digit-year] (if (< (js/parseInt two-digit-year) 50) (str "20" two-digit-year) (str "19" two-digit-year))) |
Converts three character month abrieviations into their numeral representation. It uses a simple map lookup. There is some redundancy in the map. A different implementation might use a vector of the abrieviations and get the index of the query word. | (defn convert-month [month-word] (get {"Jan" "01" "Feb" "02" "Mar" "03" "Apr" "04" "May" "05" "Jun" "06" "Jul" "07" "Aug" "08" "Sep" "09" "Oct" "10" "Nov" "11" "Dec" "12"} month-word)) |
Combine the year, month, and day strings with the correct dilimeter for ISO 8601 format. | (defn to-iso8601 [year month day] (str year \- month \- day)) |
Transforms the given function into one that takes a vector as an argument, ignoring the first value in the vector. The original function is called with the last values in the vector as individual arguments. | (defn apply-groups [f] #(apply f (rest %))) |
Format Matching This is the core function. It goes through each of the given regular expressions in sequence. When it finds one that
matches, it passes the result of The regular expressions were tested with the test input at regexr | (defn normalize-date [date] (condp re-matches date #"\d\d\d\d-\d\d-\d\d" :>> identity #"(\d\d)/(\d\d)/(\d\d)" :>> (apply-groups #(to-iso8601 (convert-year %3) %1 %2)) #"(\d\d)#(\d\d)#(\d\d)" :>> (apply-groups #(to-iso8601 (convert-year %2) %1 %3)) #"(\d\d)\*(\d\d)\*(\d\d\d\d)" :>> (apply-groups #(to-iso8601 %3 %2 %1)) #"(\w\w\w) (\d\d), (\d\d\d\d)" :>> (apply-groups #(to-iso8601 %3 (convert-month %1) %2)) #"(\w\w\w) (\d\d), (\d\d)" :>> (apply-groups #(to-iso8601 (convert-year %3) (convert-month %1) %2)) "no match")) |
ResultYou can try it out with one date at a time using the following field. | (defn single-input [] (let [value (atom "10*11*2010")] (fn [] [:div [:p "Input: " [:input {:type "text" :value @value :on-change #(reset! value (-> % .-target .-value))}] [:p "Output: " (normalize-date @value)]]]))) |
(reagent/render-component [single-input] (sel1 :#single-input)) | |
Press the button to load the test input from the gist.
| (defn test-input [input-file] [:table (for [input (string/split-lines input-file)] [:tr [:td input] [:td (normalize-date input)]])]) |
(let [button (sel1 :#test-input-button)] (dommy/listen! button :click #(GET "https://gist.githubusercontent.com/coderd00d/a88d4d2da014203898af/raw/73e9055107b5185468e2ec28b27e3b7b853312e9/gistfile1.txt" {:handler (fn [response] (reagent/render-component [test-input response] (sel1 :#test-input)))}))) | |