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
)
Related
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
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
I'm trying to solve the Fibonacci problem on codeeval. At first I wrote it in the usual recursive way and, although I got the right output, I failed the test since it used ~70MB of memory and the usage limit is 20MB. I found an approximation formula and rewrote it to use that thinking it was the heavy stack usage that was causing me to exceed the limit. However, there doesn't seem to be any reduction.
(ns fibonacci.core
(:gen-class))
(use 'clojure.java.io)
(def phi (/ (+ 1 (Math/sqrt 5)) 2))
(defn parse-int
"Find the first integer in the string"
[int-str]
(Integer. (re-find #"\d+" int-str)))
(defn readfile
"Read in a file of integers separated by newlines and return them as a list"
[filename]
(with-open [rdr (reader filename)]
(reverse (map parse-int (into '() (line-seq rdr))))))
(defn fibonacci
"Calculate the Fibonacci number using an approximatation of Binet's Formula. From
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibFormula.html"
[term]
(Math/round (/ (Math/pow phi term) (Math/sqrt 5))))
(defn -main
[& args]
(let [filename (first args)
terms (readfile filename)]
(loop [terms terms]
((comp println fibonacci) (first terms))
(if (not (empty? (rest terms)))
(recur (rest terms))))))
(-main (first *command-line-args*))
Sample input:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
50
Sample output:
0
1
1
2
3
5
8
13
21
34
55
89
144
233
12586269025
Their input is clearly much larger than this and I don't get to see it. How can I modify this code to use dramatically less memory?
Edit: It's impossible. Codeeval knows about the problem and is working on it. See here.
Codeeval is broken for Clojure. There are no accepted Clojure solutions listed and there is a message from the company two months ago saying they are still working on the problem.
Darn.
Presumably the problem is that the input file is very large, and your readfile function is creating the entire list of lines in memory.
The way to avoid that is to process a single line at a time, and not hold on to the whole sequence, something like:
(defn -main [& args]
(let [filename (first args)]
(with-open [rdr (reader filename)]
(doseq [line (line-seq rdr)]
(-> line parse-int fibonacci println)))))
Are you getting a stack overflow error? If so, Clojure supports arbitrary precision, so it might help to try using /' instead of /. The apostrophe versions of +, -, * and / are designed to coerce numbers into BigInts to prevent stack overflow.
See this question.
I wrote a piece of code to count the leading hash(#) character of a line, which is much like a heading line in Markdown
### Line one -> return 3
######## Line two -> return 6 (Only care about the first 6 characters.
Version 1
(defn
count-leading-hash
[line]
(let [cnt (count (take-while #(= % \#) line))]
(if (> cnt 6) 6 cnt)))
Version 2
(defn
count-leading-hash
[line]
(loop [cnt 0]
(if (and (= (.charAt line cnt) \#) (< cnt 6))
(recur (inc cnt))
cnt)))
I used time to measure both tow implementations, found that the first version based on take-while is 2x faster than version 2. Taken "###### Line one" as input, version 1 took 0.09 msecs, version 2 took about 0.19 msecs.
Question 1. Is it recur that slows down the second implementation?
Question 2. Version 1 is closer to functional programming paradigm , is it?
Question 3. Which one do you prefer? Why? (You're welcome to write your own implementation.)
--Update--
After reading the doc of cloujure, I came up with a new version of this function, and I think it's much clear.
(defn
count-leading-hash
[line]
(->> line (take 6) (take-while #(= \# %)) count))
IMO it isn't useful to take time measurements for small pieces of code
Yes, version 1 is more functional
I prefer version 1 because it is easier to spot errors
I prefer version 1 because it is less code, thus less cost to maintain.
I would write the function like this:
(defn count-leading-hash [line]
(count (take-while #{\#} (take 6 line))))
No, it's the reflection used to invoke .charAt. Call (set! *warn-on-reflection* true) before creating the function, and you'll see the warning.
Insofar as it uses HOFs, sure.
The first, though (if (> cnt 6) 6 cnt) is better written as (min 6 cnt).
1: No. recur is pretty fast. For every function you call, there is a bit of overhead and "noise" from the VM: the REPL needs to parse and evaluate your call for example, or some garbage collection might happen. That's why benchmarks on such tiny bits of code don't mean anything.
Compare with:
(defn
count-leading-hash
[line]
(let [cnt (count (take-while #(= % \#) line))]
(if (> cnt 6) 6 cnt)))
(defn
count-leading-hash2
[line]
(loop [cnt 0]
(if (and (= (.charAt line cnt) \#) (< cnt 6))
(recur (inc cnt))
cnt)))
(def lines ["### Line one" "######## Line two"])
(time (dorun (repeatedly 10000 #(dorun (map count-leading-hash lines)))))
;; "Elapsed time: 620.628 msecs"
;; => nil
(time (dorun (repeatedly 10000 #(dorun (map count-leading-hash2 lines)))))
;; "Elapsed time: 592.721 msecs"
;; => nil
No significant difference.
2: Using loop/recur is not idiomatic in this instance; it's best to use it only when you really need it and use other available functions when you can. There are many useful functions that operate on collections/sequences; check ClojureDocs for a reference and examples. In my experience, people with imperative programming skills who are new to functional programming use loop/recur a lot more than those who have a lot of Clojure experience; loop/recur can be a code smell.
3: I like the first version better. There are lots of different approaches:
;; more expensive, because it iterates n times, where n is the number of #'s
(defn count-leading-hash [line]
(min 6 (count (take-while #(= \# %) line))))
;; takes only at most 6 characters from line, so less expensive
(defn count-leading-hash [line]
(count (take-while #(= \# %) (take 6 line))))
;; instead of an anonymous function, you can use `partial`
(defn count-leading-hash [line]
(count (take-while (partial = \#) (take 6 line))))
edit:
How to decide when to use partial vs an anonymous function?
In terms of performance it doesn't matter, because (partial = \#) evaluates to (fn [& args] (apply = \# args)). #(= \# %) translates to (fn [arg] (= \# arg)). Both are very similar, but partial gives you a function that accepts an arbitrary number of arguments, so in situations where you need it, that's the way to go. partial is the λ (lambda) in lambda calculus. I'd say, use what's easier to read, or partial if you need a function with an arbitrary number of arguments.
Micro-benchmarks on the JVM are almost always misleading, unless you really know what you're doing. So, I wouldn't put too much weight on the relative performance of your two solutions.
The first solution is more idiomatic. You only really see explicit loop/recur in Clojure code when it's the only reasonable alternative. In this case, clearly, there is a reasonable alternative.
Another option, if you're comfortable with regular expressions:
(defn count-leading-hash [line]
(count (or (re-find #"^#{1,6}" line) "")))
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)