Ep 019: Dazed by Weak Weeks

Play Episode

Nate wants to see more than data structures in a REPL.

Related episodes:

Clojure in this episode:

Code sample from this episode:

(ns time.week-05
  (:require
    [time.week-04 :as week-04]
    [java-time :as jt]
    ))


; Date helpers

(defn start-of-week
  "Get the the starting date of the week containing local-date. The week will
  start on the named day. Eg. :sunday"
  [starting-day-of-week local-date]
  (jt/adjust local-date :previous-or-same-day-of-week (jt/day-of-week starting-day-of-week)))

(defn week-dates
  "Create a week's worth of dates starting from the given date."
  [starting-date]
  (->> (range 0 7)
       (map #(jt/plus starting-date (jt/days %)))))


; Aggregates

(defn sum-minutes
  "Sums the minutes for all kinds: entry, day, week"
  [entries]
  (->> entries
       (map :minutes)
       (reduce +)))


; Conversions

(defn entries->days
  "Convert a seq of entries to days."
  [entries]
  (->> (group-by :date entries)
       (map (fn [[date xs]] {:date date :minutes (sum-minutes xs)}))))

(defn days->week
  "Convert a seq of days into a week. Week is picked by first date."
  [starting-day-of-week days]
  (let [lookup (into {} (map (juxt :date identity) days))
        starting-date (start-of-week starting-day-of-week (:date (first days)))
        all-days (->> (week-dates starting-date)
                      (map #(or (get lookup %)
                                {:date %
                                 :minutes 0})))]
    {:starting-day-of-week starting-day-of-week
     :date starting-date
     :days (vec all-days)
     :minutes (sum-minutes all-days)}))

(defn partition-weeks
  [starting-day-of-week days]
  (->> days
       (sort-by :date)
       (partition-by #(start-of-week starting-day-of-week (:date %)))))

(defn days->weeks
  "Convert a seq of days into an ordered seq of weeks."
  [starting-day-of-week days]
  (->> (partition-weeks starting-day-of-week days)
       (map (partial days->week starting-day-of-week))))


(comment
  (->> (week-04/log-times "time-log.txt")
       (entries->days))

  (->> (week-04/log-times "time-log.txt")
       (entries->days)
       (days->weeks :sunday))
  )