Clojure 中的 Time Ago 函数实现是什么样的?

How would Time Ago function implementation look like in Clojure?

我的意思是函数,当给定时间 returns 之前的最小时间单位时。 例如

一种可能的实现方式可能如下所示:

请注意,我使用了 clj-time/clj-time · GitHub 库。

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

(defn time-ago [time]
  (let [units [{:name "second" :limit 60 :in-second 1}
               {:name "minute" :limit 3600 :in-second 60}
               {:name "hour" :limit 86400 :in-second 3600}
               {:name "day" :limit 604800 :in-second 86400}
               {:name "week" :limit 2629743 :in-second 604800}
               {:name "month" :limit 31556926 :in-second 2629743}
               {:name "year" :limit Long/MAX_VALUE :in-second 31556926}]
        diff (t/in-seconds (t/interval time (t/now)))]
    (if (< diff 5)
      "just now"
      (let [unit (first (drop-while #(or (>= diff (:limit %))
                                         (not (:limit %))) 
                                    units))]
        (-> (/ diff (:in-second unit))
            Math/floor
            int
            (#(str % " " (:name unit) (when (> % 1) "s") " ago")))))))

用法示例:

(time-ago (t/minus (t/now) (t/days 400)))
=> "1 year ago"

(time-ago (t/minus (t/now) (t/days 15)))
=> "2 weeks ago"

(time-ago (t/minus (t/now) (t/seconds 45))) 
=> "45 seconds ago"

(time-ago (t/minus (t/now) (t/seconds 1)))
=> "just now"

如果您在 JVM 上使用 Clojure,请考虑使用 PrettyTime library. Using that library for implementing "time ago" in Java was suggested here

要使用 Clojure 中的 PrettyTime 库,首先将以下内容添加到 project.clj 中的 :dependencies 向量中:

[org.ocpsoft.prettytime/prettytime "3.2.7.Final"]

然后就可以直接使用Java互操作了。我发现的一个怪癖是 "moments ago" 和其他输出之间的截止时间默认为 1 分钟。我添加了一行以将其更改为一秒钟。这个库似乎支持多种语言,这是一个优点。默认情况下它打印 "moments ago" 而不是 "just now"。如果真的很重要,那就需要花点功夫去处理了。

(import 'org.ocpsoft.prettytime.PrettyTime
       'org.ocpsoft.prettytime.units.JustNow
       'java.util.Date)

(defn time-ago [date]
  (let [pretty-time (PrettyTime.)]
    (.. pretty-time (getUnit JustNow) (setMaxQuantity 1000))
    (.format pretty-time date)))

(let [now (System/currentTimeMillis)]
  (doseq [offset [200, (* 30 1000), (* 5 60 1000)]]
     (println (time-ago (Date. (- now offset))))))

;; moments ago
;; 30 seconds ago
;; 5 minutes ago

它只支持分钟、小时和天,但如果这足够了,您可能还想看看 goog.date.relative:

https://github.com/google/closure-library/blob/master/closure/goog/date/relative.js#L87