Clojureで日付を扱う(clj-time)

clj-timeとは

Clojureで日時を扱う為にはclj-timeを使うと良い。これはJavaJodaTimeのラッパーで、イミュータブルでスレッドセーフなのでClojureからも安全に利用できる。
以下に書いてあることは基本的に上記のgithubのREADME.mdにすべて書いてある。

DateTimeオブジェクトを作る

date-time

DateTimeは時間まで指定してオブジェクトを作ることもできるし、日付だけ指定して作ることもできる。

時分秒まで指定
(date-time 1986 10 13 11 24 30)       
=> #<DateTime 1986-10-13T11:24:30.000Z>
日時まで指定
(date-time 1986 10 13)
=> #<DateTime 1986-10-13T00:00:00.000Z>

hour

DateTimeオブジェクトから時だけを取得する。同様にmonth, day, minute関数も存在する。

(day (date-time 1986 10 13 11 24 30))   
=> 13
(hour (date-time 1986 10 13 11 24 30))
=> 11
(minute (date-time 1986 10 13 11 24 30)) 
=> 24

タイムゾーンを指定する

date-time関数のコンストラクタはデフォルトでUTCタイムゾーンを返す。

from-time-zone

第1引数のDateTimeオブジェクトに対して、第2引数のタイムゾーンを設定したDateTimeオブジェクトを返す。

(from-time-zone (date-time 2013 4 1) (time-zone-for-offset +9))
=> #<DateTime 2013-04-01T00:00:00.000+09:00>

to-time-zone

第1引数のDateTimeオブジェクトに対して、第2引数のタイムゾーンを設定し、時差を計算してその時間を設定したDateTimeオブジェクトを返す。

(def time1 (from-time-zone (date-time 2013 4 1) (time-zone-for-offset +9)))
=> #'clj-time.core/time1
(to-time-zone time1 (time-zone-for-offset 0))  
=> #<DateTime 2013-03-31T15:00:00.000Z> # -9(+90の時差)された日時が入る
(to-time-zone time1 (time-zone-for-offset +10))
=> #<DateTime 2013-04-01T01:00:00.000+10:00> # +1(+9と+10の時差)された日時が入る

time-zone-for-id

タイムゾーンの指定にはtime-zone-for-offsetで時差を直接入力する以外に、タイムゾーンのIDを入力することでも指定出来る。

(to-time-zone (date-time 2013 4 1) (time-zone-for-id "Asia/Tokyo"))
=> #<DateTime 2013-04-01T09:00:00.000+09:00>

日付だけを扱う

local-date

時間を使わず、日付だけを操作したい場合はlocal-dateを使う。

(local-date 2013 10 1)
=> #<LocalDate 2013-10-01>

日時のチェック

after?関数は次の要素かどうかのチェック、before?関数は前の要素かどうかをチェックする。
これらはlocal-dateだけでなく、date-timeからでも利用出来る。また、date-timeは月まで、日まで、時間までを指定されたオブジェクトそれぞれに対してチェックの関数を使える。

次の月か?

(after? (date-time 2013 10) (date-time 2013 9)) 
=> true

次の日か?

(after? (date-time 2013 10 2) (date-time 2013 10 1))
=> true

次の時間か?

(after? (date-time 2013 10 2 10) (date-time 2013 10 2 9))
=> true

日時の演算

加算

(plus (date-time 2013 8 14) (months 3) (weeks 1))
=> #<DateTime 2013-11-21T00:00:00.000Z>

減算

(minus (date-time 2013 8 14) (months 3) (weeks 1))
=> #<DateTime 2013-05-07T00:00:00.000Z>

フォーマット

文字列をDateTimeに変換する場合、DateTimeを文字列に変換する場合はclj-time.formatを使う。

フォーマッタを作る

(def custom-formatter (formatter "yyyyMMdd"))
=> #'clj-time.core/custom-formatter

parseとunparse

(parse custom-formatter "20100311")                   
=> #<DateTime 2010-03-11T00:00:00.000Z>
(unparse custom-formatter (date-time 2010 10 3))
=> "20101003"

デフォルトで用意されたフォーマッタを使う

(def built-in-formatter (formatters :basic-date-time))
=> #'clj-time.core/built-in-formatter
(unparse built-in-formatter (date-time 2010 10 3))