Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Created June 26, 2012 04:37
Show Gist options
  • Save olivergeorge/2993312 to your computer and use it in GitHub Desktop.
Save olivergeorge/2993312 to your computer and use it in GitHub Desktop.
Some Excel date functions translated to clojure
; Date algorithms from...
; http://rjbaker.org.uk/software/datetime.html
; notleap(y)=[mod(y,4)+2)/3]
(defn NOTLEAP [y]
(TRUNC (/ (+ (mod y 4) 2) 3)))
; doy(y,m,d) = [275m/9] - [(m+9)/12] * (1+notleap(y) ) + d - 30
; = \__p1__/ + (-1 * \___p2___/ * \_____p3____/ ) + d + -30
(defn DAY_OF_YEAR [[y m d]]
(let [p1 (TRUNC (/ (* 275 m) 9))
p2 (TRUNC (/ (+ m 9) 12))
p3 (+ 1 (NOTLEAP y))]
(+ p1 (* -1 p2 p3) d -30)))
; sch(y,m,d) = trunc(( 1461(y-1900) - 1) / 4) + doy(y,m,d)
; = trunc(( \____p1____/ - 1) / 4) + \___p2___/
; = trunc(( \_______p3______/ / 4) + \___p2___/
; = trunc(( \__________p4_______/) + \___p2___/
(defn DAYS_SINCE_1900 [[y m d]]
(let [p1 (* 1461 (- y 1900))
p2 (DAY_OF_YEAR [y m d])
p3 (- p1 1)
p4 (/ p3 4)]
(TRUNC (+ p4 p2))))
; Excel incorrectly treats 1900 as a leap year
(defn EXCEL_DAYS_SINCE_1900 [[y m d]]
(let [days (DAYS_SINCE_1900 [y m d])]
(if (>= days 60)
(+ 1 days)
days)))
(defn TRUNC [num]
{:pre [(number? num)]
:post [()]}
(if (> num 0)
(Math/floor num)
(Math/ceil num)))
;Eurpoean version of DAYS360 only (Excel quirk free)
;
;360*(y2-y1)+30*(m2-m1)+(d2-d1)
;
(defn DAYS360
[[y1 m1 d1] [y2 m2 d2] method]
{:pre [(= method true)]}
(let [d1 (min d1 30)
d2 (min d2 30)]
(+ (* 360 (- y2 y1))
(* 30 (- m2 m1))
(- d2 d1))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment