Skip to content

Instantly share code, notes, and snippets.

@dyba
Last active August 29, 2015 14:14
Show Gist options
  • Save dyba/4c13973411343845bd0c to your computer and use it in GitHub Desktop.
Save dyba/4c13973411343845bd0c to your computer and use it in GitHub Desktop.
Excel's DAYS360 in Clojure
(ns days360.core
(:require [clj-time.core :as t]
[clj-time.format :as f]
[clj-time.predicates :as p]
[clj-time.periodic :as per]))
;; It works! Now to prettify it...
(defn days360
"Calculates the number of days between a start-date and end-date according to
a 360-day year."
[start-date end-date]
(let [[sd ed] (let [d1 (f/parse start-date)
d2 (f/parse end-date)]
(if (t/after? d1 d2) [d2 d1] [d1 d2]))
[sdy sdm sdd] [(t/year sd) (t/month sd) (t/day sd)]
[edy edm edd] [(t/year ed) (t/month ed) (t/day ed)]
sdd (if (p/last-day-of-month? sd)
30
sdd)
[edm edd] (if (and (p/last-day-of-month? ed)
(if (p/february? sd)
(< (t/day sd) 29)
(< (t/day sd) 30)))
[(+ 1 (t/month ed)) 1]
[(t/month ed) (min 30 (t/day ed))])]
(+ (* 360 (- edy sdy))
(* 30 (- edm sdm))
(- edd sdd))))
(ns days360.core-test
(:require [clojure.test :refer :all]
[days360.core :refer :all]))
(deftest calculating-days-between-dates
(testing "interval-in-days"
(testing "when passing the :as :360-day-yr option"
(testing "a starting date on the last day of the month is treated as the 30th"
(is (= (days360 "2008-01-30" "2008-02-01") 1))
(is (= (days360 "2015-01-31" "2015-02-01") 1))
(is (= (days360 "1996-02-29" "1996-03-01") 1))
(is (= (days360 "1993-02-28" "1993-03-01") 1))
(is (= (days360 "2008-01-30" "2008-01-31") 0))
(is (= (days360 "2008-02-29" "2008-08-31") 180))
(is (= (days360 "2008-02-29" "2008-03-30") 30))
(is (= (days360 "2008-02-29" "2008-03-31") 30))
(is (= (days360 "2008-02-28" "2008-03-31") 33))
(is (= (days360 "2008-01-01" "2008-12-31") 360))
(is (= (days360 "2008-01-01" "2008-02-01") 30))
(is (= (days360 "2015-01-01" "2015-01-31") 30))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment