我有很多日期,例如
(list #inst "2016-04-30T10:29:17.000-00:00"
#inst "2016-03-24T12:13:12.000-00:00"
#inst "2016-03-24T12:09:43.000-00:00"
#inst "2016-03-23T13:19:03.000-00:00"
#inst "2016-02-26T14:51:37.000-00:00"
#inst "2016-01-20T16:55:24.000-00:00")
我需要将它们之间的时间差计算为分钟的整数。
我搜索了Clojure时间库,但除了如何将转换为外,对#inst的库知之甚少。
如何使用#inst的seq进行时间算术以获取差异并将diff转换为分钟的整数?
感谢您的帮助。
答案 0 :(得分:1)
#inst "..."
只是一个java.util.Date
对象,因此您可以获取到距纪元以来的毫秒数:
(->> (list #inst "2016-04-30T10:29:17.000-00:00"
#inst "2016-03-24T12:13:12.000-00:00"
#inst "2016-03-24T12:09:43.000-00:00"
#inst "2016-03-23T13:19:03.000-00:00"
#inst "2016-02-26T14:51:37.000-00:00"
#inst "2016-01-20T16:55:24.000-00:00")
(map #(.. %
toInstant
(atZone (ZoneId/systemDefault))
toLocalDateTime))
(partition 2 1)
(map (fn [[a b]] (Math/abs (.until a b ChronoUnit/MINUTES)))))
=> (53236 3 1370 37347 53156)
答案 1 :(得分:1)
略微改善@akond答案(并且不使用任何外部库):
(defn diff-minutes [[x y]]
(quot (- x y) 60000))
(def l (list #inst "2016-04-30T10:29:17.000-00:00"
#inst "2016-03-24T12:13:12.000-00:00"
#inst "2016-03-24T12:09:43.000-00:00"
#inst "2016-03-23T13:19:03.000-00:00"
#inst "2016-02-26T14:51:37.000-00:00"
#inst "2016-01-20T16:55:24.000-00:00"))
(->> l (map #(.getTime %))
(partition 2 1)
(map diff-minutes))
;; or, an anonymous version
(->> l (map #(.getTime %))
(partition 2 1)
(map (fn [[x y]] (quot (- x y) 60000))))
(53176 3 1370 37347 53156)
答案 2 :(得分:1)
到目前为止,所有答案在第一个和最后一个分组中似乎相去甚远。另外,此解决方案将返回Integers作为必需的问题。
请注意,它需要Java 8 +。
(def l (list #inst "2016-04-30T10:29:17.000-00:00"
#inst "2016-03-24T12:13:12.000-00:00"
#inst "2016-03-24T12:09:43.000-00:00"
#inst "2016-03-23T13:19:03.000-00:00"
#inst "2016-02-26T14:51:37.000-00:00"
#inst "2016-01-20T16:55:24.000-00:00"))
(import 'java.time.temporal.ChronoUnit)
(->> l
(map #(.toInstant %))
(partition 2 1)
(map (fn [[a b]] (Math/abs (.between ChronoUnit/MINUTES b a)))))
将返回列表:
(53176 3 1370 37347 53156)
使用几个库clojure.math.numeric-tower和Clojure.Java-Time,我们可以执行以下操作
(require '[java-time])
(require '[clojure.math.numeric-tower :refer [abs]])
(->> l
(map java-time/instant)
(partition 2 1)
(map (comp abs (partial apply java-time/time-between :minutes))))
这将返回相同的列表。
引入xforms将使我们能够使用换能器。
(require '[java-time])
(require '[clojure.math.numeric-tower :refer [abs]])
(require '[net.cgrand.xforms :as x])
(sequence
(comp
(map java-time/instant)
(x/partition 2 1)
(map (partial apply java-time/time-between :minutes))
(map abs))
l)
并获得相同的最终结果。
答案 3 :(得分:1)
还使用本机java.time
的另一种解决方案:
(ns tst.tupelo.java-time
(:import [ java.time Duration ZoneId ZonedDateTime ]))
; note that instants are in DESCENDING order
(let [instants ["2016-04-30T10:29:17.000-00:00"
"2016-03-24T12:13:12.000-00:00"
"2016-03-24T12:09:43.000-00:00"
"2016-03-23T13:19:03.000-00:00"
"2016-02-26T14:51:37.000-00:00"
"2016-01-20T16:55:24.000-00:00"]
zoned-date-times (mapv #(ZonedDateTime/parse %) instants)
zdt-pairs (partition 2 1 zoned-date-times)
durations (vec (for [[interval-stop interval-start] zdt-pairs]
(.toMinutes ; *** truncates ***
(Duration/between interval-start interval-stop))))]
结果:
durations => [53176 3 1370 37347 53156]
请注意:如原始问题所述,这些值将被删减整分钟。
由于前两个答案是错误的,因此这表明使用java.time
的内置时间实用程序而不是尝试快速编写本地解决方案的价值。在大多数情况下,我发现使用本机Java类和函数要比使用clj-time
这样的Clojure包装器要容易得多,后者可以包装已弃用的库Joda-Time。
从Java 8开始,clj-time
(及其包装的Joda Time库)应被视为已弃用。来自the clj-time
homepage:
Clojure的日期和时间库,包装了乔达时间库。 Joda Time网站说:
请注意,从Java SE 8开始,要求用户迁移到 java.time(JSR-310)-JDK的核心部分取代了 项目。
还请注意,Joda-Time的作者还是java.time
程序包的作者,该程序包扩展了Joda-Time并纠正了一些仅随年龄增长而明显的缺点。 The Joda-Time homepage本身说:
请注意,从Java SE 8开始,要求用户迁移到 java.time(JSR-310)-JDK的核心部分取代了 项目。
由于原始时间戳记(大部分是字符串),因此我认为OP可能会更轻松地解决该问题。如果要使用Clojure #inst
语法,则答案甚至更简单:
; note that instants are in DESCENDING order
(let [instants [ #inst "2016-04-30T10:29:17.000-00:00"
#inst "2016-03-24T12:13:12.000-00:00"
#inst "2016-03-24T12:09:43.000-00:00"
#inst "2016-03-23T13:19:03.000-00:00"
#inst "2016-02-26T14:51:37.000-00:00"
#inst "2016-01-20T16:55:24.000-00:00"]
instants (mapv #(.toInstant %) instants)
inst-pairs (partition 2 1 instants)
durations (vec (for [[interval-stop interval-start] inst-pairs]
(.toMinutes ; *** truncates ***
(Duration/between interval-start interval-stop))))]
请注意,新的映射功能#(.toInstant %)
是唯一需要更改的东西。