How to add days to current date in clojure - clojure

In clojure I want to add days to current date can anyone please guide me on that. Am getting current date as below and now let's say I want to add 7 days to it, how can I get a new date?
(.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (java.util.Date.))

This would work:
(java.util.Date. (+ (* 7 86400 1000) (.getTime (java.util.Date.)))
I prefer to use System/currentTimeMillis for the current time:
(java.util.Date. (+ (* 7 86400 1000) (System/currentTimeMillis)))
Or you can use clj-time which is a nicer api to deal with time (it's a wrapper around Joda Time). From the readme file:
(t/plus (t/date-time 1986 10 14) (t/months 1) (t/weeks 3))
=> #<DateTime 1986-12-05T00:00:00.000Z>

user> (import '[java.util Calendar])
;=> java.util.Calendar
user> (defn days-later [n]
(let [today (Calendar/getInstance)]
(doto today
(.add Calendar/DATE n)
.toString)))
#'user/days-later
user> (println "Tomorrow: " (days-later 1))
;=> Tomorrow: #inst "2014-11-26T15:36:31.901+09:00"
;=> nil
user> (println "7 Days from now: " (days-later 7))
;=> 7 Days from now: #inst "2014-12-02T15:36:44.785+09:00"
;=> nil

Related

Clojure - Get hour only from Time String

I have a time string "2017-08-30 09:01:48". Is there a way to round the time to the nearest hour and return the hour?
So if the time were "2017-08-30 09:01:48" it would return 9
If the time were "2017-08-30 09:51:48" it would return 10
I looked at the library clj-time but I couldn't see anything in there that would help me
Any help would be much appreciated?
clj-time is a thin wrapper for Joda Time library. You can easily use the methods of the underlying Java objects to perform common date manipulations.
For rounding the hour, you can access the hour as a DateTime.Property and use its API to round to nearest hour as follows:
(require '[clj-time.format :as tf])
(-> (tf/parse "2017-08-30 09:01:48")
.hourOfDay
.roundHalfCeilingCopy
.getHourOfDay)
There are several rounding methods (roundCeilingCopy, roundHalfFloorCopy, etc.) to choose from, depending on your exact case.
Note also, that you don't need to specify a formatter, as your date string is already in the ISO8601 format.
If you don't want to depend on another library, don't forget, that we have new date/time API in Java 8.
Although it doesn't support rounding to the nearest hour (minute, whatever), that's quite easy to implement like madstap in his solution.
Here's the code:
(import 'java.time.LocalDateTime)
(import 'java.time.format.DateTimeFormatter)
(def date-format (DateTimeFormatter/ofPattern "yyyy-MM-dd HH:mm:ss"))
(defn- round-to-nearest-hour [date-time-string]
(let [date-time (LocalDateTime/parse date-time-string date-format)]
(if (>= 30 (.getMinute date-time))
date-time
(.plusHours date-time 1))))
(.getHour (round-to-nearest-hour "2017-08-30 09:01:48")) ;=> 9
(.getHour (round-to-nearest-hour "2017-08-30 09:31:48")) ;=> 10
This is pretty simple to do with the clj-time library.
(ns foo.hours
(:require
[clj-time.core :as time]
[clj-time.format :as timef]))
(defn parse [s]
(timef/parse (timef/formatter "yyyy-MM-dd HH:mm:ss") s))
(defn round-hour [time]
(let [m (time/minute time)
h (time/hour time)
rounded-h (if (<= 30 m) (inc h) h)]
(if (= 24 rounded-h) 0 rounded-h)))
(comment
(def f (comp round-hour parse))
(f "2017-08-30 09:20:48") ;=> 9
(f "2017-08-30 09:33:48") ;=> 10
(f "2017-08-30 23:39:48") ;=> 0
)

counting function calls in clojure

Hi I am looking for a method to count function calls in clojure so that for instance I can find out which functions are called most frequently. Ideally I would like this to be transparent to users so that if they add a function they don't know or care about this process. Any help would be greatly appreciated.
Thanking you in advance
Michael
You can store the call count in an atom and attach an accessor to the function using with-meta:
(def sqrt
(let [n (atom 0)]
(with-meta
(fn [x]
(swap! n inc)
(Math/sqrt x))
{::call-count (fn [] #n)})))
Examples:
((::call-count (meta sqrt))) ;=> 0
(sqrt 0) ;=> 0.0
(sqrt 1) ;=> 1.0
(sqrt 2) ;=> 1.4142135623730951
((::call-count (meta sqrt))) ;=> 3
(sqrt 3) ;=> 1.7320508075688772
(sqrt 4) ;=> 2.0
(sqrt 5) ;=> 2.23606797749979
((::call-count (meta sqrt))) ;=> 6
This may cause considerable slowdown in some cases, but the count will always be updated correctly because Clojure atoms are thread-safe. Another approach could be to use add-watch rather than deref, but which one is better depends on your situation. You could even use both if you want to.
You can abstract away the details with a defcounted macro to define call-counted functions and a call-count function to retrieve the call count of a call-counted function:
(defmacro defcounted [sym params & body]
`(def ~sym
(let [n# (atom 0)]
(with-meta
(fn ~params
(swap! n# inc)
~#body)
{::call-count (fn [] #n#)}))))
(defn call-count [f]
((::call-count (meta f))))
(defcounted sqrt [x]
(Math/sqrt x))
Examples:
(call-count sqrt) ;=> 0
(sqrt 0) ;=> 0.0
(sqrt 1) ;=> 1.0
(sqrt 2) ;=> 1.4142135623730951
(call-count sqrt) ;=> 3
(sqrt 3) ;=> 1.7320508075688772
(sqrt 4) ;=> 2.0
(sqrt 5) ;=> 2.23606797749979
(call-count sqrt) ;=> 6
Also, since here you're attaching the metadata to the function itself rather than to the var, you could expand this technique to anonymous functions as well.
Obviously defcounted is lacking a lot of defn's features, so it's not really transparent to the user. In fixing this problem, you could use clojure.spec to more easily parse the defn-style arguments, but I'll leave that for you to do as you see fit, as it's orthogonal to this question.

How would Time Ago function implementation look like in Clojure?

I mean function, when given time returns smallest time unit ago.
E.g
"5 minutes ago"
"30 seconds ago"
"just now"
One possible implementation might look like this:
Note, I've used clj-time/clj-time ยท GitHub library.
(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")))))))
Example usage:
(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"
If you are using Clojure on the JVM, consider using the PrettyTime library. Using that library for implementing "time ago" in Java was suggested here.
To use PrettyTime library from Clojure, first add the following to the :dependencies vector in project.clj:
[org.ocpsoft.prettytime/prettytime "3.2.7.Final"]
Then you can use Java interop directly. One quirk I found is that the cut-off between "moments ago" and other outputs is at 1 minute by default. I added a line to change that to one second. This library appears to support several languages, which is a plus. By default it prints "moments ago" instead of "just now". It would require some effort to deal with in case that is really important.
(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
It only supports minutes, hours & days but if that's sufficient you may also want to look at goog.date.relative:
https://github.com/google/closure-library/blob/master/closure/goog/date/relative.js#L87

Add days to current date

Am new to clojure, can anyone help me to understand how can I get current date in clojure and then adding days to it?
for e.g. adding 3 days to current date?
The idiomatic Clojure way is to use clj-time (see link for Leiningen/Maven install instructions), which wraps Joda time as referenced by the first answer from overthink.
user=> (use '[clj-time.core])
nil
user=> (now)
#<DateTime 2014-11-25T12:03:34.714Z>
user=> (plus (now) (days 3))
#<DateTime 2014-11-28T12:05:40.888Z>
This isn't a Clojure-specific answer, really, but I'd use Joda time.
(import 'org.joda.time.DateTime)
(let [now (DateTime/now)
later (.plusDays now 3)]
[now later])
;; [#<DateTime 2014-11-24T23:26:05.885-05:00> #<DateTime 2014-11-27T23:26:05.885-05:00>]
user> (import '[java.util Calendar])
;=> java.util.Calendar
user> (defn days-later [n]
(let [today (Calendar/getInstance)]
(doto today
(.add Calendar/DATE n)
.toString)))
#'user/days-later
user> (println "Tomorrow: " (days-later 1))
;=> Tomorrow: #inst "2014-11-26T15:36:31.901+09:00"
;=> nil
user> (println "7 Days from now: " (days-later 7))
;=> 7 Days from now: #inst "2014-12-02T15:36:44.785+09:00"
;=> nil

What's the easiest way to parse numbers in clojure?

I've been using java to parse numbers, e.g.
(. Integer parseInt numberString)
Is there a more clojuriffic way that would handle both integers and floats, and return clojure numbers? I'm not especially worried about performance here, I just want to process a bunch of white space delimited numbers in a file and do something with them, in the most straightforward way possible.
So a file might have lines like:
5 10 0.0002
4 12 0.003
And I'd like to be able to transform the lines into vectors of numbers.
You can use the edn reader to parse numbers. This has the benefit of giving you floats or Bignums when needed, too.
user> (require '[clojure.edn :as edn])
nil
user> (edn/read-string "0.002")
0.0020
If you want one huge vector of numbers, you could cheat and do this:
user> (let [input "5 10 0.002\n4 12 0.003"]
(read-string (str "[" input "]")))
[5 10 0.0020 4 12 0.0030]
Kind of hacky though. Or there's re-seq:
user> (let [input "5 10 0.002\n4 12 0.003"]
(map read-string (re-seq #"[\d.]+" input)))
(5 10 0.0020 4 12 0.0030)
Or one vector per line:
user> (let [input "5 10 0.002\n4 12 0.003"]
(for [line (line-seq (java.io.BufferedReader.
(java.io.StringReader. input)))]
(vec (map read-string (re-seq #"[\d.]+" line)))))
([5 10 0.0020] [4 12 0.0030])
I'm sure there are other ways.
If you want to be safer, you can use Float/parseFloat
user=> (map #(Float/parseFloat (% 0)) (re-seq #"\d+(\.\d+)?" "1 2.2 3.5"))
(1.0 2.2 3.5)
user=>
Not sure if this is "the easiest way", but I thought it was kind of fun, so... With a reflection hack, you can access just the number-reading part of Clojure's Reader:
(let [m (.getDeclaredMethod clojure.lang.LispReader
"matchNumber"
(into-array [String]))]
(.setAccessible m true)
(defn parse-number [s]
(.invoke m clojure.lang.LispReader (into-array [s]))))
Then use like so:
user> (parse-number "123")
123
user> (parse-number "123.5")
123.5
user> (parse-number "123/2")
123/2
user> (class (parse-number "123"))
java.lang.Integer
user> (class (parse-number "123.5"))
java.lang.Double
user> (class (parse-number "123/2"))
clojure.lang.Ratio
user> (class (parse-number "123123451451245"))
java.lang.Long
user> (class (parse-number "123123451451245123514236146"))
java.math.BigInteger
user> (parse-number "0x12312345145124")
5120577133367588
user> (parse-number "12312345142as36146") ; note the "as" in the middle
nil
Notice how this does not throw the usual NumberFormatException if something goes wrong; you could add a check for nil and throw it yourself if you want.
As for performance, let's have an unscientific microbenchmark (both functions have been "warmed up"; initial runs were slower as usual):
user> (time (dotimes [_ 10000] (parse-number "1234123512435")))
"Elapsed time: 564.58196 msecs"
nil
user> (time (dotimes [_ 10000] (read-string "1234123512435")))
"Elapsed time: 561.425967 msecs"
nil
The obvious disclaimer: clojure.lang.LispReader.matchNumber is a private static method of clojure.lang.LispReader and may be changed or removed at any time.
In my opinion the best/safest way that works when you want it to for any number and fails when it isn't a number is this:
(defn parse-number
"Reads a number from a string. Returns nil if not a number."
[s]
(if (re-find #"^-?\d+\.?\d*$" s)
(read-string s)))
e.g.
(parse-number "43") ;=> 43
(parse-number "72.02") ;=> 72.02
(parse-number "009.0008") ;=> 9.008
(parse-number "-92837482734982347.00789") ;=> -9.2837482734982352E16
(parse-number "89blah") ;=> nil
(parse-number "z29") ;=> nil
(parse-number "(exploit-me)") ;=> nil
Works for ints, floats/doubles, bignums, etc. If you wanted to add support for reading other notations, simply augment the regex.
Brian Carper's suggested approach (using read-string) works nicely, but only until you try and parse zero-padded numbers like "010". Observe:
user=> (read-string "010")
8
user=> (read-string "090")
java.lang.RuntimeException: java.lang.NumberFormatException: Invalid number: 090 (NO_SOURCE_FILE:0)
This is because clojure tries to parse "090" as an octal, and 090 is not a valid octal!
Brian carper's answer is almost correct. Instead of using read-string directly from clojure's core. Use clojure.edn/read-string. It is safe and it will parse anything that you throw at it.
(ns edn-example.core
(require [clojure.edn :as edn]))
(edn/read-string "2.7"); float 2.7
(edn/read-string "2"); int 2
simple, easy and execution safe ;)
Use bigint and bigdec
(bigint "1")
(bigint "010") ; returns 10N as expected
(bigint "111111111111111111111111111111111111111111111111111")
(bigdec "11111.000000000000000000000000000000000000000000001")
Clojure's bigint will use primitives when possible, while avoiding regexps, the problem with octal literals or the limited size of the other numeric types, causing (Integer. "10000000000") to fail.
(This last thing happened to me and it was quite confusing: I wrapped it into a parse-int function, and afterwards just assumed that parse-int meant "parse a natural integer" not "parse a 32bit integer")
These are the two best and correct approaches:
Using Java interop:
(Long/parseLong "333")
(Float/parseFloat "333.33")
(Double/parseDouble "333.3333333333332")
(Integer/parseInt "-333")
(Integer/parseUnsignedInt "333")
(BigInteger. "3333333333333333333333333332")
(BigDecimal. "3.3333333333333333333333333332")
(Short/parseShort "400")
(Byte/parseByte "120")
This lets you precisely control the type you want to parse the number in, when that matters to your use case.
Using the Clojure EDN reader:
(require '[clojure.edn :as edn])
(edn/read-string "333")
Unlike using read-string from clojure.core which isn't safe to use on untrusted input, edn/read-string is safe to run on untrusted input such as user input.
This is often more convenient then the Java interop if you don't need to have specific control of the types. It can parse any number literal that Clojure can parse such as:
;; Ratios
(edn/read-string "22/7")
;; Hexadecimal
(edn/read-string "0xff")
Full list here: https://www.rubberducking.com/2019/05/clojure-for-non-clojure-programmers.html#numbers
I find solussd's answer work great for my code. Based on it, here's an enhancement with support for Scientific notation. Besides, (.trim s) is added so that extra space can be tolerated.
(defn parse-number
"Reads a number from a string. Returns nil if not a number."
[s]
(if (re-find #"^-?\d+\.?\d*([Ee]\+\d+|[Ee]-\d+|[Ee]\d+)?$" (.trim s))
(read-string s)))
e.g.
(parse-number " 4.841192E-002 ") ;=> 0.04841192
(parse-number " 4.841192e2 ") ;=> 484.1192
(parse-number " 4.841192E+003 ") ;=> 4841.192
(parse-number " 4.841192e.2 ") ;=> nil
(parse-number " 4.841192E ") ;=> nil
(def mystring "5")
(Float/parseFloat mystring)