Clojure 中的 Time Ago 函数实现是什么样的?
How would Time Ago function implementation look like in Clojure?
我的意思是函数,当给定时间 returns 之前的最小时间单位时。
例如
- “5 分钟前”
- “30 秒前”
- "just now"
一种可能的实现方式可能如下所示:
请注意,我使用了 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
我的意思是函数,当给定时间 returns 之前的最小时间单位时。 例如
- “5 分钟前”
- “30 秒前”
- "just now"
一种可能的实现方式可能如下所示:
请注意,我使用了 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