Как добавить дни к дате в Clojure
Я посмотрел на следующий вопрос: Как добавить дни к текущей дате в clojure.
Однако я очень новичок в Clojure, и я застрял в следующем сценарии, я получаю метку времени в строковом формате. Поэтому я анализирую его, используя следующее:
(.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") date)
Что дает мне результат, который выглядит так:
#inst "2015-02-13T00:20:00.000-00:00"
Как добавить, скажем, 90 дней к этому, а затем преобразовать его обратно в формат строки? Я попробовал это на основе вышеуказанной ссылки:
(java.util.Date. (+ (* 7 86400 1000)
(.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") date)))
Который дал мне следующую ошибку:
ClassCastException java.util.Date cannot be cast to java.lang.Number clojure.lang.Numbers.add
4 ответа
parse
возвращает java.util.Date
, ошибка, которую вы видите, говорит вам, что вы не можете разыграть Date
к Number
, Ты можешь использовать getTime
чтобы получить миллисекунды Date
:
(java.util.Date. (+ (* 7 86400 1000)
(.getTime (.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") date))))
Это потенциально добавляет 7 дней к дате. Если вы хотите добавить 90 дней, вам нужно заменить 7 на 90, например: (* 90 86400 1000)
,
Вы также можете использовать java.util.Calendar
:
(let [cal (Calendar/getInstance)
d (.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") date)]
(doto cal
(.setTime d)
(.add Calendar/DATE 90)
(.getTime)))
Или еще лучше, clj-time:
(require '[clj-time.core :as t])
(require '[clj-time.format :as f])
(t/plus (f/parse (f/formatters :year-month-day) date)
(t/days 90))
Я не рекомендовал бы использовать устаревший API даты и времени в новом коде, если вы можете избежать этого.
В Java 8 появился новый API для дат, с помощью которых вы можете элегантно выразить эту проблему:
(let [date-format java.time.format.DateTimeFormatter/ISO_LOCAL_DATE]
(.. (java.time.LocalDate/parse "2015-02-13" date-format)
(plusDays 90)
(format date-format)))
Или даже, принимая все ярлыки:
(-> (java.time.LocalDate/parse "2015-02-13") (.plusDays 90) str)
clj-time имеет from-now
а также ago
:
(require '[clj-time.core :refer [days from-now]])
(-> 90 days from-now)
=> #object[org.joda.time.DateTime 0x4d8bcee3 "2017-01-11T16:03:40.067Z"]
(require '[clj-time.core :refer [hours ago]])
(-> 7 hours ago)
=> #object[org.joda.time.DateTime 0x3eef2142 "2016-10-13T09:19:01.246Z"]
Имеется в наличии PeriodType
определения: years
, months
, weeks
, days
, hours
, minutes
, seconds
,
В результате Йода DateTime
Объектами можно легко манипулировать, например, до эпохи Unix за миллисекунды:
(require '[clj-time.coerce :as coerce])
(coerce/to-long (-> 90 days from-now))
=> 1484150620067
Это решение возвращает java.util.Date
:
(defn add-days-to-instant [num-days ^java.util.Date d]
(.getTime (let [cal (Calendar/getInstance)]
(doto cal
(.setTime d)
(.add Calendar/DATE num-days)))))