rbb
rbb

Reputation: 999

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?

Upvotes: 3

Views: 915

Answers (3)

Juraj Martinka
Juraj Martinka

Reputation: 4358

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

Upvotes: 4

Toni Vanhala
Toni Vanhala

Reputation: 1372

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.

Upvotes: 6

madstap
madstap

Reputation: 1552

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

  )

Upvotes: 2

Related Questions