正在寻找在Clojure中按月划分日期的方法

正在寻找在Clojure中按月划分日期的方法,clojure,clojure-java-interop,Clojure,Clojure Java Interop,希望将日期范围拆分为每月的数据块 输入示例-[2019年10月20日-2019年12月20日] 示例输出-{[10/20/2019 10/31/2019][11/01/2019 11/30/2019][12/012019 12/20/2019]} 谢谢这里是一个简单的草案,说明了您可以做什么(使用java interop,无需外部LIB): 首先,让我们按月进行迭代,从指定的迭代开始: (defn by-month [[mm yyyy]] (iterate #(.plusMonths % 1

希望将日期范围拆分为每月的数据块

输入示例-
[2019年10月20日-2019年12月20日]

示例输出-
{[10/20/2019 10/31/2019][11/01/2019 11/30/2019][12/012019 12/20/2019]}


谢谢

这里是一个简单的草案,说明了您可以做什么(使用java interop,无需外部LIB):

首先,让我们按月进行迭代,从指定的迭代开始:

(defn by-month [[mm yyyy]]
  (iterate #(.plusMonths % 1)
           (java.time.YearMonth/of yyyy mm))) 

user> (take 4 (by-month [10 2019]))
;;=> (#object[java.time.YearMonth 0x62fc8302 "2019-10"]
;;    #object[java.time.YearMonth 0x1a7bc211 "2019-11"]
;;    #object[java.time.YearMonth 0x6a466e83 "2019-12"]
;;    #object[java.time.YearMonth 0x652ac30f "2020-01"])
然后获取每个年月的开始和结束日期:

(defn start-end [^java.time.YearMonth ym]
  [(.atDay ym 1) (.atEndOfMonth ym)])

;;=> ([#object[java.time.LocalDate 0xe880abb "2019-10-01"]
;;     #object[java.time.LocalDate 0x54aadf50 "2019-10-31"]]
;;    [#object[java.time.LocalDate 0x14c1b42d "2019-11-01"]
;;     #object[java.time.LocalDate 0x32d0a22c "2019-11-30"]])
现在,按照输入日期将其包装为范围函数:

(defn day-range [[mm1 dd1 yyyy1] [mm2 dd2 yyyy2]]
  (let [start (java.time.LocalDate/of yyyy1 mm1 dd1)
        end (java.time.LocalDate/of yyyy2 mm2 dd2)
        internal (->> [mm1 yyyy1]
                      by-month
                      (mapcat start-end)                     
                      (drop 1)
                      (take-while #(neg? (compare % end))))]
    (partition 2 `(~start ~@internal ~end))))

user> (day-range [10 20 2019] [12 20 2019])
;;=> ((#object[java.time.LocalDate 0x6a8f92f2 "2019-10-20"]
;;     #object[java.time.LocalDate 0x10135df3 "2019-10-31"])
;;    (#object[java.time.LocalDate 0x576bcff7 "2019-11-01"]
;;     #object[java.time.LocalDate 0x7b5ed908 "2019-11-30"])
;;    (#object[java.time.LocalDate 0x6b2117a9 "2019-12-01"]
;;     #object[java.time.LocalDate 0x57bf0864 "2019-12-20"]))
现在,您可以根据需要对每个开始-结束对进行后处理:

(map (fn [[^java.time.LocalDate start ^java.time.LocalDate end]]
       (let [fmt (java.time.format.DateTimeFormatter/ofPattern "MM/dd/yyyy")]
         [(.format start fmt) (.format end fmt)]))
     (day-range [10 20 2019] [12 20 2019]))

;;=> (["10/20/2019" "10/31/2019"]
;;    ["11/01/2019" "11/30/2019"]
;;    ["12/01/2019" "12/20/2019"])
另一种方法是按天迭代,然后按[月-年]分区,先收集后收集:

(defn ranges [[mm1 dd1 yyyy1] [mm2 dd2 yyyy2]]
  (let [start (java.time.LocalDate/of yyyy1 mm1 dd1)
        end (java.time.LocalDate/of yyyy2 mm2 dd2)]
    (->> start
         (iterate (fn [^java.time.LocalDate curr] (.plusDays curr 1)))         
         (take-while (fn [^java.time.LocalDate dt] (not (pos? (compare dt end)))))
         (partition-by (fn [^java.time.LocalDate dt] [(.getMonthValue dt) (.getYear dt)]))
         (map (juxt first last)))))

user> (ranges [10 20 2019] [12 20 2019])
;;=> ([#object[java.time.LocalDate 0x383f6a9e "2019-10-20"]
;;     #object[java.time.LocalDate 0x2ca14c39 "2019-10-31"]]
;;    [#object[java.time.LocalDate 0x74d1974 "2019-11-01"]
;;     #object[java.time.LocalDate 0x5f6c16cc "2019-11-30"]]
;;    [#object[java.time.LocalDate 0x74f63a42 "2019-12-01"]
;;     #object[java.time.LocalDate 0x4b90c388 "2019-12-20"]])

这会产生一些不必要的中间VAL,但也为您提供了一种按需拆分范围的方法。

直接Java互操作是实现此目的的方法:

  (let [start-ld  (LocalDate/parse "2019-10-20")
        start-bom (.with start-ld (TemporalAdjusters/firstDayOfMonth))
        start-eom (.with start-ld (TemporalAdjusters/lastDayOfMonth))]

start-bom => #object[java.time.LocalDate 0x1a69aaa8 "2019-10-01"]
start-eom => #object[java.time.LocalDate 0x329970b5 "2019-10-31"]
您可以按如下方式增加月份:

        next-bom  (.plusMonths start-bom 1)
得到

next-bom => #object[java.time.LocalDate 0x21ced418 "2019-11-01"]
然后您可以编写一个循环。

您可以使用:

(请参阅clojure:exclude[范围迭代格式最大-最小])
(使用“java时间”)
(->>(迭代加上(当地日期2019年10月20日)(第1天))
(在当地日期2019年12月21日?%之前)
(按月划分)
(地图(fn[日期][(第一个日期)(最后一个日期)])
输出:

([#object[java.time.LocalDate 0x26c16faf "2019-10-20"]
  #object[java.time.LocalDate 0x4113c834 "2019-10-31"]]
 [#object[java.time.LocalDate 0x7d0a5212 "2019-11-01"]
  #object[java.time.LocalDate 0x249fe02f "2019-11-30"]]
 [#object[java.time.LocalDate 0x7345f070 "2019-12-01"]
  #object[java.time.LocalDate 0x26d66577 "2019-12-20"]])


到目前为止你试过什么?试着用这个。没有得到预期的结果。是的,这个问题足够具体,可以吸引到正确的答案,不应该关闭。